I am working on creating a WCF restful API in VB.Net and so far getting data from the MSSQL databbase with one parameter and saving data are currently working. Currently I am trying to create a service contract with multiple parameters (email and password) to authenticate user login. This keeps throwing the following error and I just can not figure out how to resolve this:
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:--
This is my service contract:
<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)
And this is the ValidateLogin Function that is called:
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) = "$2y$" 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
Finally, this is my 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>
I have looked into many posts to find hints to this matter but I did not get anywhere.
Posts I have looked at:
Why do I get this WCF error when 'GET'ing?
How to send email address as parameter in wcf method
http://jeffbarnes.net/blog/post/2006/10/16/metadata-exchange-endpoint.aspx
After trying out different approaches, I have finally solved where I went wrong.
The parameter names for the functions need to named same as the parameters specified in the UriTemplate.
Original:
Fix: