Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't resolve/use System.ServiceModel.Security.WSTrustServiceContract as service name

Tags:

I have a token issuer WCF service which is using Microsoft.IdentityModel (WIF 3.5) that I need to upgrade to System.IdentityModel (.NET 4.5). The problem is that I can't change the original name of the service , Microsoft.IdentityModel.Protocols.WSTrust.WSTrustServiceContract, to it's newer counterpart, System.ServiceModel.Security.WSTrustServiceContract. For some reason it's not recognized by IntelliSense:

enter image description here

The blue squiggly line error is:

The 'name' attribute is invalid - The value 'System.ServiceModel.Security.WSTrustServiceContract' is invalid according to its datatype 'serviceNameType'

I do have assembly references to System.ServiceModel and System.IdentityModel in <assemblies> node.

Even when I ignore the IntelliSense error and run the service and access it using browser I'm getting this metadata error:

Metadata publishing for this service is currently disabled. 

Metadata publishing is enabled so I think it's because of the name problem of the service.

Also I'm getting this error from the VS.NET WCF test client:

Error: Cannot obtain Metadata from http://localhost:49178/Services/Issuer.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 http://go.microsoft.com/fwlink/?LinkId=65455.
WS-Metadata Exchange Error    
URI: http://localhost:49178/Services/Issuer.svc    
Metadata contains a reference that cannot be resolved: 'http://localhost:49178/Services/Issuer.svc'.    
There was no endpoint listening at http://localhost:49178/Services/Issuer.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.    
The remote server returned an error: (404) Not Found.
HTTP GET Error    
URI: http://localhost:49178/Services/Issuer.svc    
The HTML document does not contain Web service discovery information.

I think the "Metadata contains a reference that cannot be resolved" line also refers to the service name resolve error.

Any ideas on what to do here? I'd appreciate any help..

Issuer.svc:

<%@ ServiceHost Language="C#" Debug="true" Factory="Identity.Services.Wcf.Core.CustomSecurityTokenServiceContractFactory" Service="CustomSecurityTokenServiceConfiguration"  %>

Factory:

public class CustomSecurityTokenServiceContractFactory : WSTrustServiceHostFactory
..

Service:

public class CustomSecurityTokenServiceConfiguration : SecurityTokenServiceConfiguration
..
like image 898
dstr Avatar asked Dec 22 '17 14:12

dstr


1 Answers

Sometimes the best way to solve this kind of problems is to create a new WCF project from scratch, configure again your endpoints etc.. and copying over your existing services from your old project, this is especially true when moving from an older version of WCF.

Here is a checklist that I follow every time I have problems with WCF services:

The Server

Make sure your service contracts are defined using interfaces with the appropriate attributes, for example:

IMyService.cs

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    int ThisAnOperation(int a, int b);
}

Check that you have implemented your contracts using the right interface:

MyService.cs

public class MyService: IMyService
{
    public int ThisAnOperation(int a, int b)
    {
        return a * b;
    }
}

You need to have a service host to access your service, they are the files with the extension .svc:

  • Create a file myService.svc.
  • Add the following line of code, referencing the class implementing your service:

    <%@ ServiceHost Language="C#" Debug="true" Service="YourNamespace.MyService" CodeBehind="MyService.cs" %>

Finally, you need to set up a binding which will define which transports and protocols are available to access your server, start with a simple basic HTTP binding to check that your service is working as expected, then change it to something more production ready that includes authentication and/or encryption and compression as needed.

To setup basic HTTP binding:

  1. Remove the block <system.serviceModel>...</system.serviceModel> from your file web.config if it's already there.

  2. Build your solution, it should compile successfully, otherwise fix any error and try again.

  3. Right-click your web.config file and then click on "Edit WCF Configuration", then click on "Create a New Service" and in Service type, browse and choose the DLL file generated when you compiled your service (should be in the bin folder) and select the service class you would like to publish:

Service Selection

  1. Specify the contract for the service (should be automatically filled up).

  2. In the next page select the transport protocol for your service, in this case, "HTTP", then select "Basic Web Services interoperability".

  3. In the next page you can specify the address for the endpoint, for testing purposes, you can leave this field empty (make sure you also remove "HTTP" from the text field).

  4. Click next, close the configuration window and save.

Now you should be able to run the service and browse to MyService.svc to access your service.

  1. Activate metadata publishing so your service can be found, to do this, add the following behavior to your web.config:

    <system.serviceModel>
        <services>
            <service name="WcfService1.MyService">
                <endpoint binding="basicHttpBinding"
                       bindingConfiguration="" contract="WcfService1.IMyService" 
                    BehaviorConfiguration="MyServiceBehaviors" />
             </service>
         </services>
    </system.serviceModel>
    
    <behaviors>
         <serviceBehaviors>
             <behavior name="MyServiceBehaviors" >
                 <serviceMetadata httpGetEnabled="true" />
             </behavior>
         </serviceBehaviors>
    </behaviors>
    

Now you should be able to run your project and get a metadata description page of your service within the browser, this info can be used by clients to find the service and generate a proxy of the service:

The Client

  1. Delete any existing service references from your project.
  2. Right click on your project name then in "Add Service Reference", input your service address and click on "Go", if everything went all right you should see your service in the Service Window:

Service Reference

  1. Try to generate the proxy by finishing the wizard, rebuild your project and try it. If you still have the same problem, delete the generated reference and repeat points 1 and 2 and then:

  2. Click on "Advanced" and uncheck "Reuse types in referenced assemblies":

Advanced service settings

Then finish the wizard and compile.

Hopefully, everything should work now!!!

like image 200
Isma Avatar answered Sep 22 '22 12:09

Isma