wcf中处理application/hal+json格式
Deal with application/hal+json format in wcf
我设置了一个已配置的 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
有什么想法请
您可以使用 WebContentTypeMapper 向 WCF 指示您希望以与 "regular" JSON 相同的方式对待 application/hal+json
(即 application/json
)。下面的代码显示了使用映射器的示例。
public class Whosebug_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();
}
}
我设置了一个已配置的 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
有什么想法请
您可以使用 WebContentTypeMapper 向 WCF 指示您希望以与 "regular" JSON 相同的方式对待 application/hal+json
(即 application/json
)。下面的代码显示了使用映射器的示例。
public class Whosebug_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();
}
}