20

我有一个使用 Json.NET (newtonsoft) 作为自定义序列化程序的工作应用程序。目前,我正在自定义 WebServiceHostFactory 中添加 WebHttpBehavior 的这种派生。请参阅本博客末尾的代码片段,了解我是如何附加它的。

当我在 IIS 中托管此服务时,我想摆脱我的自定义托管代码,只需将自定义行为添加到我的 web.config。此msdn 文章中显示了该过程。

所以我尝试这样做:

<behaviors>
  <endpointBehaviors>
    <behavior name="jsonRest">
      <webHttp defaultOutgoingResponseFormat="Json" />
      <NewtonsoftJsonBehavior/>
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<extensions>
  <behaviorExtensions>
    <add name="NewtonsoftJsonBehavior" type="Newtonsoft.Json.Extensions.NewtonsoftJsonBehavior, NewtonsoftJsonExtensions, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </behaviorExtensions>
</extensions>

可悲的是,我无法完成这项工作。当我这样做时,Visual Studio 会告诉我

元素“行为”具有无效的子元素“NewtonsoftJsonBehavior”

在上述msdn文章中,据说

要向元素添加配置功能,您需要编写并注册一个配置元素。有关这方面的更多信息,请参阅System.Configuration文档。

定义元素及其配置类型后,就可以使用扩展名了,如下例所示。

我有这种感觉,我所缺少的正是这一点。以某种方式注册元素及其配置类型。可悲的是,我无法对System.Configuration做出正面或反面,它应该告诉我如何做到这一点。所以这基本上是我的问题:

我如何编写和注册配置元素,如果这不是我的问题,那么问题是什么?

提前谢谢了!

4

2 回答 2

40

缺少的部分是 BehaviorExtensionElement 类。在 OP 中,我试图将 WebHttpBehavior-derivative 添加为元素。BehaviorExtensionElement 告诉配置解析器哪个类型用于某个元素。

这是我需要的实现:

public class NewtonsoftJsonBehaviorExtension : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(NewtonsoftJsonBehavior); }
    }

    protected override object CreateBehavior()
    {
        return new NewtonsoftJsonBehavior();
    }
}

当然,这还不足以摆脱我的自定义 WebServiceHostFactory。因为我还必须添加一个自定义 ContentTypeMapper:

public class NewtonsoftJsonContentTypeMapper : WebContentTypeMapper
{
    public override WebContentFormat GetMessageFormatForContentType(string contentType)
    {
        return WebContentFormat.Raw;
    }
}

然后我可以在我的 Web.config 中使用它们。以下是工作配置的相关部分。首先设置扩展并使用它配置行为:

<extensions>
  <behaviorExtensions>
    <add name="newtonsoftJsonBehavior" type="Newtonsoft.Json.Extensions.NewtonsoftJsonBehaviorExtension, NewtonsoftJsonExtensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </behaviorExtensions>
</extensions>
<behaviors>
  <endpointBehaviors>
    <behavior name="jsonRestEndpointBehavior">
      <webHttp/>
      <newtonsoftJsonBehavior/>
    </behavior>
  </endpointBehaviors>
<behaviors>

然后使用我的自定义 contentTypeMapper 配置 webHttpBinding:

<bindings>
  <webHttpBinding>
    <binding name="newtonsoftJsonBinding" contentTypeMapper="Newtonsoft.Json.Extensions.NewtonsoftJsonContentTypeMapper, NewtonsoftJsonExtensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
  </webHttpBinding>
</bindings>

最后使用上述设置一个端点:

<services>
  <service name="My.Namespaced.MyService" behaviorConfiguration="jsonRestServiceBehavior">
    <endpoint address=""                behaviorConfiguration="jsonRestEndpointBehavior"
              binding="webHttpBinding"  bindingConfiguration="newtonsoftJsonBinding" 
              contract="My.Namespaced.IMyService" />
  </service>
</services>

希望这些东西可以帮助那里的人。:)

于 2011-11-11T16:47:45.543 回答
2

如果您使用 svcconfigeditor 打开此 app.config,它应该开始要求选择与 NewtonsoftJsonBehavior 关联的程序集。如果您选择该选项并再次保存 app.config,是否可以解决您的问题?

顺便说一句,我们还在服务配置中使用自定义绑定扩展。配置中的 xml 始终用蓝色波浪在扩展下划线,表明该元素对于您描述的模式不知道。但是,当我们启动服务时,服务和行为都按预期运行。

于 2011-11-10T21:14:38.917 回答