2011-04-20 3 views
2

J'ai un service WCF qui fonctionne quand on y accède par une simple application MVC.erreur d'incompatibilité de contrat WCF en utilisant Autofac pour enregistrer via endpoint ChannelFactory

Lorsque je tente de faire appel sur le même point final à partir d'une autre application MVC qui est câblé avec Autofac je reçois une exception non-concordance de contrat liant/ comme ceci:

Content Type application/soap+xml; charset=utf-8 was not supported by service http://localhost:6985/ProductService.svc . The client and service bindings may be mismatched.

System.Net.WebException: The remote server returned an error: (415) Unsupported Media Type.

Je suis raisonnablement confiant que je n'ai pas une incompatibilité dans les paramètres de configuration à chaque extrémité, je base cette confiance sur le test des mêmes paramètres sur une combinaison WCF + MVC où Autofac n'est pas présent. Les paramètres de configuration sont sur pastebin.com/t7wfR77h.

Je voudrais donc une analyse de l'aide si la façon dont je l'ai enregistré la dépendance/point final avec Autofac est la question ...

* Code Application_Start * dans l'application MVC pour la configuration Autofac:

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)); 

(pour être complet) où je fais usage de c'est dans un ProductController qui a seulement 1 dépendance à injecter, très simple:

public class ProductController : AsyncController 
{ 
    private IProductService _service; 

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

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

On dirait un problème de configuration de WCF pour moi, pas grand-chose à suggérer que - quelques indices sur le web ... http://blogs.msdn.com/b/endpoint/archive/2010/11/01/wcf- webhttp-service-retours-http-415-unsupported-media-type.aspx Bonne chance! –

+0

@Nicholas, merci d'avoir regardé cela, espérait que ce n'était pas un problème de WCF donc il serait facilement résoluble. –

+0

@neontapir peut-être que vous devriez poster votre code comme réponse, comme j'ai abandonné à ce sujet et ne l'a pas fonctionné;) –

Répondre

2

Comme mentionné dans le commentaire à @ Nick Josevski, j'ai été en mesure d'obtenir quelque chose de similaire au travail.

Dans ma méthode application MVC3 Application_Start, je le code suivant:

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 
} 

Ces enregistrements se rassemblent les données de configuration de WCF de web.config. J'ai également obtenu des enregistrements pour travailler avec des points finaux définis dans le code. Pour être complet, voici quelques-unes des entrées pertinentes Web.config côté client:

<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> 

Puis, dans mon contrôleur, j'ai le code comme suit:

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); 
    } 
} 

tests unitaires ressemble à ceci:

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); 
} 

Je valide disposition avec un test unitaire défini dans une classe de base de test de commande abstraite:

[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(); 
    } 
} 

Une chose que je ne sais pas encore est de savoir si cette utilisation de Owned<T> et Dispose() me donne l'élimination adéquate, ou si je vais avoir besoin d'utiliser un LifetimeScope selon An Autofac Lifetime Primer.