Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF Service attributes ignored

Tags:

c#

.net

asp.net

wcf

I'm following this MSDN article on how to implement Username authentication for WCF services.

in step 5, an attribute: [AspNetCompatibilityRequirements] is set on the service to configure the WCF service for ASP.NET compatibility mode. This is required because authentication is done by the HTTP module and you must be able to get the principal and the identity from the HTTP context in order to authorize users either imperatively or declaratively in WCF.

When I run the service I get this error message:

The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the service type with RequirementsMode setting as 'Allowed' or 'Required'.

It seems like even though I explicitly declared the attribute it's ignored. What can be the reason for this? Even if I change the value to AspNetCompatibilityRequirementsMode.Allowed it does'nt work. Same error message which is weired because then IIS has no reason to complain!

Service:

namespace MyNamespace.IISServiceHost
{
    [ServiceBehavior(MaxItemsInObjectGraph = int.MaxValue)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class CompanyNameAPIService
    {
        public CompanyNameAPIService()
        {
        }
    }
}

Interface

namespace MyNamespace
{
    [ServiceContract]
    public interface ICompanyAPI
    {
        [OperationContract]
        [PrincipalPermission(SecurityAction.Demand, Role="WSIuser")]
        [ServiceKnownType(typeof(Supplier))]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        void AddUpdateSuppliers(int companyId, Supplier[] sups);

        [OperationContract]
        [PrincipalPermission(SecurityAction.Demand, Role = "WSIuser")]
        [ServiceKnownType(typeof(Dimension))]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        void AddUpdateDimension(int companyId, Dimension dims);

        ...
    }
}

I also set the equivalent in Web.config.

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="True" multipleSiteBindingsEnabled="true" />
    <service behaviorConfiguration="ServiceBehavior" name="MyNamespace.IISServiceHost.CompanyAPIService">
        <endpoint address="" behaviorConfiguration="largeDataBehavior" 
            binding="basicHttpBinding" bindingConfiguration="BasicBindingConfiguration" 
            name="BasicEndpoint" contract="MyNamespace.ICompanyAPI" />
        <endpoint address="help" behaviorConfiguration="helpPageBehavior" 
            binding="mexHttpsBinding" bindingConfiguration="" name="MexEndpoint" 
            contract="MyNamespace.ICompanyAPI" 
            kind="mexEndpoint" endpointConfiguration="" />
    </service>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicBindingConfiguration"><security mode="Transport" /></binding>
        </basicHttpBinding>
        <webHttpBinding>
            <binding name="webBinding">
                <security mode="Transport"><transport clientCredentialType="None" /></security>
            </binding>
    </webHttpBinding>
    </bindings>
    <behaviors>
        <endpointBehaviors>
            <behavior name="largeDataBehavior">
                <dataContractSerializer maxItemsInObjectGraph="2147483647" />
                <enableWebScript />
            </behavior>
            <behavior name="helpPageBehavior">
                <webHttp helpEnabled="true" />
            </behavior>
        </endpointBehaviors>
        <serviceBehaviors>
            <behavior name="ServiceBehavior">
                <serviceMetadata httpsGetEnabled="true" httpsGetUrl="https://localhost/WSI/service.svc/wsdl" />
                <serviceDebug httpsHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
                <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="WSIRoleProvider">
                    <authorizationPolicies>
                        <add policyType="myNamespace.AuthorizationPolicy.HttpContextPrincipalPolicy, AuthorizationPolicy, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                    </authorizationPolicies>
                </serviceAuthorization>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>
like image 955
David Avatar asked Nov 08 '13 16:11

David


1 Answers

I finally got my Service working. Im posting this in case someone encounters this problem. There was several problems so I answer them one by one.

Service Attributes ignored

My Visual Studio solution contains both a Service-Project and a ServiceHost-project. The Service project has a app.config and the ServiceHost has a web.config.

What I didn't know was that even though the service is defined in web.config not all settings are honored, so instead you must make the configurations in the app.config file. This was so confusing to me because the app.config file disappears when the Service is published to IIS. I still don't know how it works, but it is.

Service Name attribute

After I fixed the first problem the Service published successfully and I could navigate to it using a Browser. the WSDL-configuration was also available (nice). But when I tried to call any of the exposed Methods of the service I got "404 not found" or "There was no channel actively listening at 'xxx'".

After a long time of trying to spot the problem I found this error in the trace log: No matching <service> tag was found.

This was weird because I knew that the service and its endpoints was configured correctly.

The issue here was the name of the service. According to numerous questions here on StackOverflow the name should be in the format of "Complete.Namespace.Classname". Apparently this is not true if the service is hosted in IIS. Then the name of service should instead be the value found in @ServiceHost tag property Service in file service.svc

like image 51
David Avatar answered Oct 29 '22 15:10

David