I have a WCF Service running on my windows 2019 server on IIS. The service is to be consumed by a .Net Core library being used within a xamarin enviornment. Everything was working fine, until I wanted to add my custom UserNamePasswordValidator in order to add some security to the service.
My Web.config service section for the server looks like this
<system.serviceModel>
<services>
<service name="aircu_web.UpdateService" behaviorConfiguration="debug">
<endpoint address="" name="wsHttpEndpoint" binding="wsHttpBinding" bindingConfiguration="ServiceBinding" contract="aircu_web.IUpdateService" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="ServiceBinding">
<security mode ="Message">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="production">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="debug">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="84 d2 c6 d8 85 17 48 30 04 9e 12 e0 bd f4 f3 36 c1 57 b5 6e" storeName="My"/>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="aircu_web.ApiKeyValidator,aircu_web"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
when navigating to https://(mydomain)/UpdateService.svc I can see the "You have created a service" site.
When I add a service reference to my assembly, the wizard is working fine and I get all the code generated, except for the binding and the endpoint address - which is new to me. Before the change to the service, there were no additional parameters for the constructor of my service client neccessary.
When I create a client with the following code and make a call to the api
var binding = new BasicHttpsBinding();
var ep = new EndpointAddress(@"https://(my domain)/UpdateService.svc");
var svc = new AirCU.Service.UpdateServiceClient(binding, ep);
I get the exception There was no endpoint listening at https://(my domain)/UpdateService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."
I guess somewhere there is an issue in my configuration, either client or server...
What do I need to change in order to get everything back working? :)
Thanks a lot
CodePudding user response:
Okay I figured it out myself.
Xamarin and .Net Standard do not support wsHttpEndpoints. I had to switch to a basicHttpsBinding, Xamarin does not support security mode TransportWithMessageCredential, so I had to stick with Transport only.
In the end my Web.config section looks like this:
<system.serviceModel>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<services>
<service name="aircu_web.UpdateService" behaviorConfiguration="debug">
<endpoint address="" name="HttpsEndpoint" binding="basicHttpsBinding" bindingConfiguration="ServiceBinding" contract="aircu_web.IUpdateService" />
</service>
</services>
<bindings>
<basicHttpsBinding>
<binding name="ServiceBinding" maxReceivedMessageSize="1000000">
<security mode ="Transport">
<message clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpsBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="production">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="debug">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate storeLocation="LocalMachine" x509FindType="FindByThumbprint" findValue="84 d2 c6 d8 85 17 48 30 04 9e 12 e0 bd f4 f3 36 c1 57 b5 6e" storeName="My"/>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="aircu_web.ApiKeyValidator,aircu_web"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
I also had to change my client code accordingly.
private UpdateService.UpdateServiceClient GetProxy()
{
var binding = new BasicHttpsBinding();
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.Security.Mode = BasicHttpsSecurityMode.Transport;
var ep = new EndpointAddress(@"https://(mydomain)/UpdateService.svc");
var svc = new UpdateService.UpdateServiceClient(binding, ep);
svc.ClientCredentials.UserName.UserName = "App";
svc.ClientCredentials.UserName.Password = "****";
return svc;
}
I also had to move my service reference from my library project to my xamarin project, because there was some assembly mismatching of the System.ServiceModel libraries I could not figure out.
I tried installing the same nuget packages to all project, removing them, clearing bin and obj folders, re-creating the project - nothing worked. So I moved the whole service reference to the xamarin project and now it works fine. Maybe someone can tell me what went wrong there. The Error was "Type (some number) unknown...."