【问题标题】:Deal with application/hal+json format in wcfwcf中处理application/hal+json格式
【发布时间】:2016-06-02 16:19:37
【问题描述】:

我设置了一个配置的 URL 端点(使用 wcf 和 POST 方法),以便在我的客户端发生某些事情时触发。当请求的内容类型设置为 application/json 时效果很好,但设置为 application 时效果不佳/json+hal,我的客户想要使用。 我的问题是如何处理这件事以及我必须改变什么。下面是我的方法在接口中的定义:

[WebInvoke(Method = "POST", UriTemplate = "/payload", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
string payload(requestpayload jsondata);

我更新了我的web.config 以考虑@carlosfigueira 的建议:

<services>
      <service behaviorConfiguration="RestServiceBehavior" name="RestRaw.RestService">
        <endpoint address="http://mywebsite.com/RestService.svc" binding="customBinding" bindingConfiguration="RawReceiveCapable" contract="RestRaw.IRestService" behaviorConfiguration="Web">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="RestServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="Web">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <customBinding>
        <binding name="RawReceiveCapable">
          <webMessageEncoding webContentTypeMapperType="RestRaw.JsonHalMapper, RestRaw" />
          <httpTransport manualAddressing="true"  />
        </binding>

      </customBinding>

但是,我得到了这个:

500 System.ServiceModel.ServiceActivationException

大家有什么意见

【问题讨论】:

    标签: c# json web-services wcf hal-json


    【解决方案1】:

    您可以使用 WebContentTypeMapper 向 WCF 指示您希望将 application/hal+json 以与“常规” JSON 相同的方式处理(即 application/json)。下面的代码展示了一个使用映射器的例子。

    public class StackOverflow_37597194
    {
        [ServiceContract]
        public interface ITest
        {
            [WebInvoke(Method = "POST",
                UriTemplate = "/payload",
                RequestFormat = WebMessageFormat.Json,
                ResponseFormat = WebMessageFormat.Json,
                BodyStyle = WebMessageBodyStyle.Bare)]
            string payload(RequestPayload jsondata);
        }
        [DataContract]
        public class RequestPayload
        {
            [DataMember(Name = "_links")]
            public RequestPayloadLinks Links { get; set; }
            [DataMember(Name = "currency")]
            public string Currency { get; set; }
            [DataMember(Name = "status")]
            public string Status { get; set; }
            [DataMember(Name = "total")]
            public double Total { get; set; }
        }
        [DataContract] public class LinkObject
        {
            [DataMember(Name = "href")]
            public string Href { get; set; }
        }
        [DataContract]
        public class RequestPayloadLinks
        {
            [DataMember(Name = "self")]
            public LinkObject Self { get; set; }
            [DataMember(Name = "warehouse")]
            public LinkObject Warehouse { get; set; }
            [DataMember(Name = "invoice")]
            public LinkObject Invoice { get; set; }
        }
        public class Service : ITest
        {
            public string payload(RequestPayload jsondata)
            {
                return string.Format("{0} - {1} {2}", jsondata.Status, jsondata.Total, jsondata.Currency);
            }
        }
        public class JsonHalMapper : WebContentTypeMapper
        {
            public override WebContentFormat GetMessageFormatForContentType(string contentType)
            {
                if (contentType.StartsWith("application/hal+json"))
                {
                    return WebContentFormat.Json;
                }
                else
                {
                    return WebContentFormat.Default;
                }
            }
        }
    
        public static void Test()
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
            var endpoint = host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding { ContentTypeMapper = new JsonHalMapper() }, "");
            endpoint.EndpointBehaviors.Add(new WebHttpBehavior());
            host.Open();
            Console.WriteLine("Host opened");
    
            WebClient c = new WebClient();
            var requestData = @"   {
                '_links': {
                    'self': { 'href': '/orders/523' },
                    'warehouse': { 'href': '/warehouse/56' },
                    'invoice': { 'href': '/invoices/873' }
                },
                'currency': 'USD',
                'status': 'shipped',
                'total': 10.20
            }".Replace('\'', '\"');
            Console.WriteLine(requestData);
            c.Headers[HttpRequestHeader.ContentType] = "application/hal+json";
            try
            {
                var response = c.UploadString(baseAddress + "/payload", "POST", requestData);
                Console.WriteLine(response);
            }
            catch (WebException ex)
            {
                Console.WriteLine("Exception: {0}", ex);
            }
    
            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }
    

    【讨论】:

    • 谢谢@carlosfigueira,我尝试了你的建议。但是,我得到了这个:500 System.ServiceModel.ServiceActivationException
    • 激活异常响应的正文是什么?它是否有关于异常的更多详细信息?或者您也可以启用跟踪,您应该会看到它无法打开服务的原因。
    • 我解决了我的问题。一般来说,我使用 WebContentTypeMapper 正如@carlosfigueira 所说。然后我改变了我的 web.config,因为它是上面提到的,但是有了这个更新:
    猜你喜欢
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 2018-01-09
    • 1970-01-01
    • 2018-06-05
    • 2010-11-29
    相关资源
    最近更新 更多