WCF WebInvoke可以接受内容类型:text / plain?

时间:2016-03-25 08:24:55

标签: c# wcf amazon-web-services amazon-sns

我正在编写WCF REST服务以使用我的WCF REST服务接收AWS SNS通知消息。

但是,WCF REST仅支持XML和JSON,但由于遗留原因,Amazon SNS使用Content-Type: text/plain; charset=UTF-8标头发布了通知,根据Amazon documentation

POST / HTTP/1.1
Content-Type: text/plain; charset=UTF-8
// ...

{
  "Type" : "Notification",
  // ...
  "UnsubscribeURL" : "https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&..."
}

当我用这个" text / plain"来呼叫我的服务时像亚马逊这样的内容类型,有一个错误,上面写着:

  

请求错误。

     

服务器在处理请求时遇到错误。异常消息是'传入消息具有意外的消息格式' Raw'。该操作的预期消息格式是' Xml&#39 ;; '的Json&#39 ;.这可能是因为尚未在绑定上配置WebContentTypeMapper。有关更多详细信息,请参阅WebContentTypeMapper的文档。'。有关详细信息,请参阅服务器日志。

我目前的代码:

public interface MyServiceInterface
{
    [OperationContract]
    [WebInvoke(Method = "POST", UriTemplate = "/AmazonIPChanges")]
    Task AmazonIPChanges(SNSNotificationMessage data);
}

[DataContract]
public class SNSNotificationMessage
{
    [DataMember]
    public string Type { get; set; }
    // ...
    [DataMember]
    public string UnsubscribeURL { get; set; }
} 

DataContract映射到Amazon SNS消息。当我使用content-type" application / json"执行POST时,此代码正常工作,但我怎样才能让它接受亚马逊的text / plain内容类型?

1 个答案:

答案 0 :(得分:3)

您可以通过创建和应用自定义WebContentTypeMapper来解决此问题,如错误消息所示。它应该是这样的:

namespace StackOverflow36216464
{
    public class RawContentTypeMapper : WebContentTypeMapper
    {
        public override WebContentFormat GetMessageFormatForContentType(string contentType)
        {
            switch (contentType.ToLowerInvariant())
            {
                case "text/plain":
                case "application/json":
                    return WebContentFormat.Json;
                case "application/xml":
                    return WebContentFormat.Xml;
                default:
                    return WebContentFormat.Default;
            }
        }
    }
}

这个解释请求的内容类型,并返回相应的WebContentFormat枚举成员。

然后,您可以以自定义绑定的形式将其应用于您的服务:

<system.serviceModel>
    <bindings>
        <customBinding>
            <binding name="textPlainToApplicationJson">
                <webMessageEncoding webContentTypeMapperType="StackOverflow36216464.RawContentTypeMapper, StackOverflow36216464, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                <httpTransport manualAddressing="true" />
            </binding>
        </customBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="debugServiceBehavior">
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
        <endpointBehaviors>
            <behavior name="restEndpointBehavior">
                <webHttp />
            </behavior>
        </endpointBehaviors>
    </behaviors>
    <services>
        <service
          name="StackOverflow36216464.Service1"
          behaviorConfiguration="debugServiceBehavior">
            <host>
                <baseAddresses>
                    <add baseAddress="http://localhost:65393/"/>
                </baseAddresses>
            </host>
            <endpoint address=""
                  binding="customBinding"
                  contract="StackOverflow36216464.IService1"
                  behaviorConfiguration="restEndpointBehavior"
                  bindingConfiguration="textPlainToApplicationJson"/>        
        </service>
    </services>
</system.serviceModel>

相关部分是配置自定义映射器的<customBinding>元素,以及应用它的servcices/service/endpoint/bindingConfiguration属性。