具有多个参数的 WCF Restful API

WCF Restful API with multiple parameter

我正致力于在 VB.Net 中创建 WCF restful API,到目前为止,使用一个参数从 MSSQL 数据库获取数据并保存数据目前正在运行。 目前我正在尝试创建一个具有多个参数(电子邮件和密码)的服务合同来验证用户登录。这不断抛出以下错误,我只是不知道如何解决这个问题:

Error: Cannot obtain Metadata from localhost:12345/SMPCService.svc If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange Error URI: localhost:12345/SMPCService.svc Metadata contains a reference that cannot be resolved: localhost:12345/SMPCService.svc'. The requested service, 'localhost:12345/SMPCService.svc' could not be activated. See the server's diagnostic trace logs for more information.HTTP GET Error URI: localhost:12345/SMPCService.svc There was an error downloading '/localhost:12345/SMPCService.svc'. The request failed with the error message:--

这是我的服务合同:

<OperationContract()>
<WebInvoke(Method:="GET", ResponseFormat:=WebMessageFormat.Json, BodyStyle:=WebMessageBodyStyle.Wrapped, UriTemplate:="ValidateLogin/{e}/{p}")>
Function ValidateLogin(ByVal sEmailAddress As String, ByVal sPassword As String) As List(Of CheckLogin)

这是调用的 ValidateLogin 函数:

Public Function ValidateLogin(ByVal sEmailAddress As String, ByVal sPassword As String) As List(Of CheckLogin) Implements ISMPCService.ValidateLogin
    Dim result As List(Of CheckLogin) = New List(Of CheckLogin)
    Dim uAction = New CheckLogin
    Dim pwd As String = ""
    Try
        ' Dimension Local Variables
        Dim uRecSnap As ADODB.Recordset

        ' Check For Open Connection
        If uDBase Is Nothing Then
            OpenConnection()
            bConnection = True
        End If

        ' Run Stored Procedure - Load Timesheet Record
        uCommand = New ADODB.Command
        With uCommand
            .ActiveConnection = uDBase
            .CommandType = ADODB.CommandTypeEnum.adCmdStoredProc
            .CommandTimeout = 0
            .Parameters.Append(.CreateParameter("@EmailAddress", ADODB.DataTypeEnum.adVarChar, ADODB.ParameterDirectionEnum.adParamInput, 30, sEmailAddress))
            .CommandText = "API_WebUser_ValidateLogin"
            uRecSnap = .Execute
        End With

        ' Populate List
        Do Until uRecSnap.EOF
            pwd = If(IsDBNull(uRecSnap("UserPassword").Value), "", uRecSnap("UserPassword").Value)
            uRecSnap.MoveNext()
        Loop
        uRecSnap = Nothing

        If pwd <> "" Then
            If pwd.Substring(0, 4) = "y$" Then
                Mid(pwd, 3, 1) = "a"
            End If

            If BCrypt.Net.BCrypt.Verify(SHA512Hash(sPassword), pwd) Then
                uAction.WasSuccessful = "OK"
                uAction.StatusDescription = "User credentials match"
            Else
                uAction.WasSuccessful = "FAIL"
                uAction.StatusDescription = "Failed to authorize user"
            End If

        Else
            uAction.WasSuccessful = "FAIL"
            uAction.StatusDescription = "Failed to authorize user"
        End If

        result.Add(uAction)
    Catch ex As Exception
        ' Catch Error
        If Err.Number <> 0 Then
            Console.WriteLine(ex.Message)
        End If

    Finally
        ' CleanUp

        ' Close Database Connection
        If bConnection Then CloseConnection()

    End Try

    Return result
End Function

最后,这是我的 Web.config:

<?xml version="1.0"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <!--Disabled custom errors to allow display of detailed errors.-->
    <customErrors mode="Off"/>
    <compilation debug="true" strict="false" explicit="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" relaxedUrlToFileSystemMapping="true"/>
  </system.web>
  <system.serviceModel>
    <services>
      <!--Specify services the application hosts. 
      Name specifies the type that provides an implementation of a service contract.
      Behavior Configuration specifies the name of one of the behaviours found in the behaviours element and governs actions such as whether the service allows impersonation.-->
      <service name="SMPCWebService.SMPCService" behaviorConfiguration="SMPCWebService.SMPCServiceBehaviour">
        <!--Define the service endpoints.-->  
        <endpoint address="../SMPCService.svc" behaviorConfiguration="webBehaviour" binding="webHttpBinding" contract="SMPCWebService.ISMPCService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
          <behavior name="SMPCWebService.SMPCServiceBehaviour">
            <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
            <serviceMetadata httpGetEnabled="true"/>
            <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
            <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
      <!--Define the endpoint behaviour.-->
      <endpointBehaviors>
        <behavior name="webBehaviour">
          <webHttp />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <!-- Allowing Cross-Origin Resource Sharing (CORS) - The httpProtocol settings allow web services to be called from external domains using JavaScript-->
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Headers" value="Content-Type, Accept" />
      </customHeaders>
    </httpProtocol>
    <modules runAllManagedModulesForAllRequests="true"/>
    <httpErrors errorMode="Detailed" />
    <validation validateIntegratedModeConfiguration="false"/>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

我查看了很多帖子以找到有关此事的提示,但我一无所获。

我看过的帖子:

Why do I get this WCF error when 'GET'ing?

Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.`

How to send email address as parameter in wcf method

http://jeffbarnes.net/blog/post/2006/10/16/metadata-exchange-endpoint.aspx

在尝试了不同的方法后,我终于解决了错误的地方。

函数的参数名称需要与 UriTemplate 中指定的参数命名相同。

原文:

<OperationContract()>
<WebInvoke(Method:="GET", ResponseFormat:=WebMessageFormat.Json, BodyStyle:=WebMessageBodyStyle.Wrapped, UriTemplate:="ValidateLogin/{e}/{p}")>
Function ValidateLogin(ByVal sEmailAddress As String, ByVal sPassword As String) As List(Of CheckLogin)

修复:

<OperationContract()>
<WebInvoke(Method:="GET", ResponseFormat:=WebMessageFormat.Json, BodyStyle:=WebMessageBodyStyle.Wrapped, UriTemplate:="ValidateLogin/{e}/{p}")>
Function ValidateLogin(ByVal e As String, ByVal p As String) As List(Of CheckLogin)