使用Autofac通过ChannelFactory注册端点的WCF合同不匹配错误

时间:2011-04-20 06:12:29

标签: wcf exception .net-4.0 autofac

我有一个WCF服务,当通过简单的MVC应用程序访问时可以正常工作。

当我尝试使用另一个连接Autofac 的MVC应用在同一端点上进行调用时,我得到绑定/合同不匹配异常,如下所示:

  

内容类型application / soap + xml;   服务http://localhost:6985/ProductService.svc不支持charset = utf-8。   客户端和服务绑定可能不匹配。

     

System.Net.WebException:远程服务器返回错误:(415)不支持的媒体类型。

我有理由相信我两端的配置设置都不匹配,我基于测试在没有Autofac的WCF + MVC组合上完全相同的设置。配置设置位于pastebin.com/t7wfR77h

因此,我想帮助分析一下我用Autofac注册依赖/端点的方式是不是......

*用于Autofac设置的MVC应用程序中的Application_Start *代码:

var builder = new ContainerBuilder();
//other registrations...

builder.Register(c => 
            new ChannelFactory<IProductService>(
                new WSHttpBinding("ProductService_wsHttpBinding"),
                new EndpointAddress("http://localhost:6985/ProductService.svc")
            )
        ).SingleInstance();

builder.Register(c =>
        {
            var factory = c.Resolve<ChannelFactory<IProductService>>();
            return factory.CreateChannel();
        }
      ).InstancePerHttpRequest();

var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

(为了完整性)我在使用它的一个ProductController中只注入了1个依赖项,非常简单:

public class ProductController : AsyncController
{
    private IProductService _service;

    public ProductController(IProductService ps)
    {
        _service = ps;
    }

    //...
    //later simply call
    _service.SomeMethod();
}

1 个答案:

答案 0 :(得分:2)

正如@Nick Josevski的评论所述,我能够得到类似的东西。

在我的MVC3应用程序的Application_Start方法中,我有以下代码:

protected void Application_Start()
{
    var builder = new ContainerBuilder();
    builder.Register(c => new ChannelFactory<ICartService>("CartService")).SingleInstance();
    builder.Register(c => c.Resolve<ChannelFactory<ICartService>>().CreateChannel()).InstancePerHttpRequest();
    var container = builder.Build();
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

    // other MVC startup activities, like registering areas and routes
}

这些注册从Web.config收集WCF配置数据。我还获得了注册以使用代码中定义的端点。为了完整起见,这里有一些相关的客户端Web.config条目:

<system.serviceModel>
  <bindings>
    <basicHttpBinding>
      <binding name="BasicHttpBinding" ... />
    </basicHttpBinding>
  </bindings>
  <client>
    <endpoint address="http://localhost:50930/Purchasing/CartService.svc"
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding"
        contract="CartService.ICartService" name="CartService" />
  </client>
</system.serviceModel>

然后,在我的控制器中,我有如下代码:

using Autofac.Features.OwnedInstances;

public class BulkCartController : Controller
{
    private readonly Owned<ICartService> cartService_;

    public BulkCartController(Owned<ICartService> cartService)
    {
        cartService_ = cartService;
    }

    protected override void Dispose(bool disposing) // defined in Controller
    {
        cartService_.Dispose();
        base.Dispose(disposing);
    }

    //
    // GET: /BulkCart/Get/1
    public ActionResult Get(int id)
    {
        var model = new ShoppingCart { ShoppingCartId = id };
        using (var cartService = cartService_)
        {
            model.Items = cartService.Value.GetCartProductItems(id);
        }
        return View("Get", model);
    }
}

单元测试如下所示:

using Autofac.Features.OwnedInstances;
using Autofac.Util;
using Moq;

[TestMethod]
public void Get_ReturnsItemsInTheGivenCart()
{
    var mock = new Mock<ICartService>(MockBehavior.Strict);
    mock.Setup(x => x.GetCartProductItems(2)).Returns(new CartProductItemViewObject[0]);
    var controller = new BulkCartController(new Owned<ICartService>(mock.Object, new Autofac.Util.Disposable())); 
    var result = controller.Get(2);

    Assert.IsInstanceOfType(result, typeof(ViewResult));
    var view = (ViewResult)result;
    Assert.AreEqual("Get", view.ViewName);

    Assert.IsInstanceOfType(view.ViewData.Model, typeof(ShoppingCart));
    var model = (ShoppingCart)view.ViewData.Model;
    Assert.AreEqual(2, model.ShoppingCartId);
    Assert.AreEqual(0, model.Items.Length);
}

我使用抽象控制器测试基类中定义的单元测试来验证处理:

[TestClass]
public abstract class ControllerWithServiceTestBase<TController, TService>
    where TController : Controller
    where TService : class
{
    [TestMethod]
    public virtual void Dispose_DisposesTheService()
    {
        var disposable = new Mock<IDisposable>(MockBehavior.Strict);
        disposable.Setup(x => x.Dispose()).Verifiable();

        var controller = (TController) Activator.CreateInstance(typeof(TController), new Owned<TService>(null, disposable.Object));
        controller.Dispose();

        disposable.Verify();
    }
}

我不知道的一件事是Owned<T>Dispose()的这种使用是否足以让我得到足够的处理,或者我是否需要按照{LifetimeScope使用{{1}} 3}}。