WCF Service exception error when try to host in AS

2019-05-09 23:45发布

The following error occurs when trying to browse my .svc file.

An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.NullReferenceException: Object reference not set to an instance of an object.
   at System.ServiceModel.Description.WsdlExporter.CreateWsdlBindingAndPort(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName, Port& wsdlPort, Boolean& newBinding, Boolean& bindingNameWasUniquified)
   at System.ServiceModel.Description.WsdlExporter.ExportEndpoint(ServiceEndpoint endpoint, XmlQualifiedName wsdlServiceQName)
   at System.ServiceModel.Description.WsdlExporter.ExportEndpoints(IEnumerable`1 endpoints, XmlQualifiedName wsdlServiceQName)
   at System.ServiceModel.Description.ServiceMetadataBehavior.MetadataExtensionInitializer.GenerateMetadata()
   at System.ServiceModel.Description.ServiceMetadataExtension.EnsureInitialized()
   at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.InitializationData.InitializeFrom(ServiceMetadataExtension extension)
   at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.GetInitData()
   at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.TryHandleDocumentationRequest(Message httpGetRequest, String[] queries, Message& replyMessage)
   at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.ProcessHttpRequest(Message httpGetRequest)
   at System.ServiceModel.Description.ServiceMetadataExtension.HttpGetImpl.Get(Message message)
   at SyncInvokeGet(Object , Object[] , Object[] )
   at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

Here is my web.config configuration:

  <system.serviceModel>
    <services>
      <service name="WcfServiceLib.WcfService"
               behaviorConfiguration="Default">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/WebService"/>
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address supplied above -->
        <endpoint address="" binding="wsHttpBinding" contract="WcfServiceContractLib.IWcfContract"/>
        <endpoint address="web" binding="webHttpBinding" contract="WcfServiceContractLib.IWcfContract"
                  behaviorConfiguration="web"/>
        <endpoint address="webJson" binding="webHttpBinding" contract="WcfServiceContractLib.IWcfContract"
                behaviorConfiguration="webJson"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp defaultOutgoingResponseFormat="Xml" helpEnabled="true"/>
        </behavior>
        <behavior name="webJson">
          <webHttp defaultOutgoingResponseFormat="Json" helpEnabled="true"/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="Default">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled ="true" />
  </system.serviceModel>

Anyone with this similar situation?

I should mention that when this is hosted in a console application I use to run tests everything is fine.

[EDIT] Same error occurs when trying to load the service in a console app. Not showing the WCF web page where you can see the wsdl info etc...

2条回答
贪生不怕死
2楼-- · 2019-05-10 00:22

If you are using .NET 4.0 and trying to host SOAP, Xml and Json endpoints togeather you would get the exception. Just commment out either your Json or Xml endpoint and that should work fine.

This is a known issue which I have raised on Microsoft Connect and the MS dev team has closed it out as won't fix.

In order to support both Json and Xml if the client passes just the required Accept header in the request like "application/xml" or "application/json" the framework autoamtically handles it and sends back the response in appropriate format.

查看更多
【Aperson】
3楼-- · 2019-05-10 00:25

This is what I've got working:

Create a WCF Class Library project in VS2012.

Xsd Schema for data types:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="urn:wcf:hydra:datatypes.xsd:1.5" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:wcf:hydra:datatypes.xsd:1.5" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="IncomingDocument">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Firstname" type="xs:string"/>
                <xs:element name="Surname" type="xs:string"/>
                <xs:element name="ChildrensNames" minOccurs="0">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="ChildsName" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
                <xs:element name="Gender" minOccurs="0">
                    <xs:simpleType>
                        <xs:restriction base="xs:string">
                            <xs:enumeration value="Male"/>
                            <xs:enumeration value="Female"/>
                            <xs:enumeration value="Other"/>
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
            </xs:sequence>
            <xs:attribute name="Version" type="xs:string" use="required" fixed="1.5"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="ResponseDocument">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="NumberOfChildren" type="xs:int"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="DayDetails">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="CurrentDateTime" type="xs:dateTime"/>
                <xs:element name="WeatherDetails" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Two ServiceContracts, note one adds the magic word, [XmlSerializserFormat]

[ServiceContract]
public interface ITestMutliHeadService
{
    [OperationContract]
    [WebInvoke(UriTemplate = "loadchildren")]
    ResponseDocument LoadChildren(IncomingDocument request);

    [OperationContract]
    [WebGet(UriTemplate = "daydetails")]
    DayDetails DayDetails();

    [OperationContract]
    [WebGet(UriTemplate = "test/{input}")]
    string Test(string input);
}

[ServiceContract]
[XmlSerializerFormat]
public interface ITestMutliHeadServiceSchemaCompliant : ITestMutliHeadService
{
}

Implement your concrete class with the two interfaces:

public sealed class TestMutliHeadService : ITestMutliHeadService, ITestMutliHeadServiceSchemaCompliant
{
    public ResponseDocument LoadChildren(IncomingDocument request)
    {
        int count = 0;
        if (request.ChildrensNames != null)
        {
            count = request.ChildrensNames.Count();
        }

        return new ResponseDocument()
        {
            NumberOfChildren = count,
        };
    }

    public DayDetails DayDetails()
    {
        return new DayDetails()
        {
            CurrentDateTime = DateTime.Now,
            WeatherDetails = "It's rather nice, really.",
        };
    }

    public string Test(string input)
    {
        return input;
    }
}

Now create a blank ASP.NET project and add a web.config and a Global.asax and a reference to System.ServiceModel.Activation

Global.asax.cs:

public class Global : HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        RegisterRoutes();
    }

    private void RegisterRoutes()
    {
        var factory = new ServiceHostFactory();
        RouteTable.Routes.Add(new ServiceRoute("", factory, typeof(TestMutliHeadService)));
    }
}

Here's the magic monster, system.serviceModel in web.config:

<system.serviceModel>
    <!-- Services -->
    <services>
      <service name="WCF.Hydra.BL.TestMutliHeadService">
        <endpoint name="restJson"       address="rest/json" behaviorConfiguration="restJsonEndpointBehaviour" binding="webHttpBinding"    bindingConfiguration="restBindingConfig"       contract="WCF.Hydra.BL.ITestMutliHeadService"/>
        <endpoint name="restJsonSecure" address="rest/json" behaviorConfiguration="restJsonEndpointBehaviour" binding="webHttpBinding"    bindingConfiguration="restSecureBindingConfig" contract="WCF.Hydra.BL.ITestMutliHeadService"/>
        <endpoint name="restXml"        address="rest/xml"  behaviorConfiguration="restXmlEndpointBehaviour"  binding="webHttpBinding"    bindingConfiguration="restBindingConfig"       contract="WCF.Hydra.BL.ITestMutliHeadServiceSchemaCompliant"/>
        <endpoint name="restXmlSecure"  address="rest/xml"  behaviorConfiguration="restXmlEndpointBehaviour"  binding="webHttpBinding"    bindingConfiguration="restSecureBindingConfig" contract="WCF.Hydra.BL.ITestMutliHeadServiceSchemaCompliant"/>
        <endpoint name="mex"            address="mex"       behaviorConfiguration=""                          binding="mexHttpBinding"    bindingConfiguration="mexBindingConfig"        contract="WCF.Hydra.BL.ITestMutliHeadService"/>
        <endpoint name="mexSecure"      address="mex"       behaviorConfiguration=""                          binding="mexHttpsBinding"   bindingConfiguration="mexSecureBindingConfig"  contract="WCF.Hydra.BL.ITestMutliHeadService"/>
        <endpoint name="soapXsd"        address="soap"      behaviorConfiguration=""                          binding="basicHttpBinding"  bindingConfiguration="soapBindingConfig"       contract="WCF.Hydra.BL.ITestMutliHeadService"/>
        <endpoint name="soapXsdSecure"  address="soap"      behaviorConfiguration=""                          binding="basicHttpsBinding" bindingConfiguration="soapSecureBindingConfig" contract="WCF.Hydra.BL.ITestMutliHeadService"/>
      </service>
    </services>
    <!--  Binding Configurations -->
    <bindings>
      <webHttpBinding>
        <binding name="restBindingConfig">
          <security mode="None"/>
        </binding>
        <binding name="restSecureBindingConfig">
          <security mode="Transport"/>
        </binding>
      </webHttpBinding>
      <mexHttpBinding>
        <binding name="mexBindingConfig"/>
      </mexHttpBinding>
      <mexHttpsBinding>
        <binding name="mexSecureBindingConfig"/>
      </mexHttpsBinding>
      <basicHttpsBinding>
        <binding name="soapSecureBindingConfig">
          <security mode="Transport"/>
        </binding>
      </basicHttpsBinding>
      <basicHttpBinding>
        <binding name="soapBindingConfig">
          <security mode="None"/>
        </binding>
      </basicHttpBinding>
    </bindings>
    <!-- Behaviour Configurations -->
    <behaviors>
      <endpointBehaviors>
        <behavior name="restJsonEndpointBehaviour">
          <webHttp helpEnabled="true" defaultBodyStyle="Bare" defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="false" faultExceptionEnabled="true" />
        </behavior>
        <behavior name="restXmlEndpointBehaviour">
          <webHttp helpEnabled="true" defaultBodyStyle="Bare" defaultOutgoingResponseFormat="Xml" automaticFormatSelectionEnabled="false" faultExceptionEnabled="true" />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <!-- Hosting Environment Settings -->
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
  </system.serviceModel>

Browse to /soap for soap, /rest/json for restful json and /rest/xml for schema-compliant-ish xml.

查看更多
登录 后发表回答