【问题标题】:How do I host a rest service with autofac and wcf?如何使用 autofac 和 wcf 托管休息服务?
【发布时间】:2016-08-31 02:16:30
【问题描述】:

按照本指南,我设法获得了一个在 iis 上运行的服务。 https://code.google.com/p/autofac/wiki/WcfIntegration#Self-Hosted_Services

但是,我还需要它托管一个休息服务。我实际上只能靠休息来生活。

但是有了可用的文档,我还没有成功。

有没有人有一个很好的指南来让它与 wcf(was)+autofac 一起使用休息服务?

我似乎没有得到正确的端点,实际上根本没有端点。

我的代码,我哪里漏掉了什么?

namespace WcfServiceHost.Infrastructure
{
    public class AutofacContainerBuilder
    {

        public static IContainer BuildContainer()
        {
            var builder = new ContainerBuilder();
            builder.RegisterType<LoginFactory>().As<ILoginFactory>();
            builder.RegisterType<SupplierHandler>().As<ISupplierHandler>();
            builder.RegisterType<UserHandler>().As<IUserHandler>();
            builder.RegisterType<SupplierRepository>().As<ISupplierRepository>();
            builder.RegisterType<TidsamProductSupplierProxy>().As<ILogin>();

            builder.RegisterType<StoreService>().As<IStoreService>();
            //builder.RegisterType<StoreService>();

            return builder.Build();
        }
    }
}



<%@ ServiceHost Language="C#" Debug="true" 
    Service="Services.IStoreService, Services" 
    Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf"
     %>



namespace WcfServiceHost.App_Code
// ReSharper restore CheckNamespace
{
    public static class AppStart
    {
        public static void AppInitialize()
        {
            // Put your container initialization here.
            // build and set container in application start
            IContainer container = AutofacContainerBuilder.BuildContainer();
            AutofacHostFactory.Container = container;

            // AutofacWebServiceHostFactory  AutofacServiceHostFactory
            RouteTable.Routes.Add(new ServiceRoute("StoreService", new RestServiceHostFactory<IStoreService>(), typeof(StoreService)));

        }
    }
}



 public class RestServiceHostFactory<TServiceContract> : AutofacWebServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);
            var webBehavior = new WebHttpBehavior
            {
                AutomaticFormatSelectionEnabled = true,
                HelpEnabled = true,
                FaultExceptionEnabled = true
            };
            var endpoint = host.AddServiceEndpoint(typeof(TServiceContract), new WebHttpBinding(), "Rest");
            endpoint.Behaviors.Add(new WebHttpBehavior { HelpEnabled = true });
            endpoint.Name = "rest";
            endpoint.Behaviors.Add(webBehavior);

            return host;
        }

    }

配置:

<system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true">
      <serviceActivations>
        <add factory="Autofac.Integration.Wcf.AutofacServiceHostFactory"
         relativeAddress="~/StoreService.svc"
         service="Services.StoreService" />
      </serviceActivations>
    </serviceHostingEnvironment>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </modules>
    <handlers>
      <add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" />
    </handlers>
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

然后我确实得到了一个端点。但是,一旦我更改为 AutofacWebServiceHostFactory,我就没有端点,也没有休息/帮助。但是,我可以在 IStoreService 中查询其余的服务。

【问题讨论】:

    标签: wcf rest autofac


    【解决方案1】:

    注册 REST WCF 服务几乎类似于注册非 REST WCF 服务。只改变了一些东西:绑定、端点和服务契约。

    autofac wiki 中使用 WCF REST 服务的修改示例(非常简化)。

    将成为依赖项的记录器的接口和实现。

    public interface ILogger
    {
        void Write(string message);
    }
    
    public class Logger : ILogger
    {
        public void Write(string message)
        {
            Console.WriteLine(message);
        }
    }
    

    其余 wcf 服务的契约和实现。

    [ServiceContract]
    public interface IEchoService
    {
        [OperationContract]
        [WebGet(UriTemplate = "/Echo/{message}")]
        string RestEcho(string message);
    }
    
    public class EchoService : IEchoService
    {
        private readonly ILogger _logger;
    
        public EchoService(ILogger logger)
        {
            _logger = logger;
        }
    
        public string RestEcho(string message)
        {
            _logger.Write(message);
            return message;
        }
    }
    

    用于构建容器和托管 Web 服务的控制台应用程序代码。

    class Program
    {
        static void Main()
        {
            ContainerBuilder builder = new ContainerBuilder();
            builder.Register(c => new Logger()).As<ILogger>();
            builder.Register(c => new EchoService(c.Resolve<ILogger>())).As<IEchoService>();
    
            using (IContainer container = builder.Build())
            {
                Uri address = new Uri("http://localhost:8080/EchoService");
                ServiceHost host = new ServiceHost(typeof(EchoService), address);
    
                var binding = new WebHttpBinding();
                var endpointAddress = new EndpointAddress(address);
                var description = ContractDescription.GetContract(typeof(IEchoService));
                var endpoint = new ServiceEndpoint(description, binding, endpointAddress);
                endpoint.Behaviors.Add(new WebHttpBehavior { HelpEnabled = true });
                host.AddServiceEndpoint(endpoint);
    
                host.AddDependencyInjectionBehavior<IEchoService>(container);
    
                host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true, HttpGetUrl = address });
                host.Open();
    
                Console.WriteLine("The host has been opened.");
                Console.ReadLine();
    
                host.Close();
                Environment.Exit(0);
            }
        }
    }
    

    为了测试,运行任何浏览器并打开一个url http://localhost:8080/EchoService/Echo/test_test

    【讨论】:

    • 感谢您的努力,我会仔细查看,看看是否遗漏了一些可以帮助我的东西。但是,我寻求有关 wcf(was) 的帮助,因为我会将它托管在 iis 上的 ms 2012 服务器上。当我在 autofac wiki 上按照关于它的指南进行操作时,它适用于肥皂,但是当我切换到 webhttpbinding 并使用 AutofacWebServiceHostFactory 时,我没有让它工作。如果你能做到,如果你碰巧住在斯德哥尔摩,我会给你几杯啤酒!
    • 我刚刚更新了我的原始帖子,说明了我的进步程度,稍微修改了代码。
    【解决方案2】:

    解决这个问题。我删除了配置中对 autofac AutofacServiceHostFactory 的引用。然后我用行为手动编写端点。

    我在服务的 .svc 文件中使用了 AutofacServiceHostFactory。

    这不是我喜欢的方式,否则我不会同时使用 rest 端点和 basichttp soap 端点。

    如果有人有更好的解决方案,我会给你答案。


    @约翰·迈耶 根据要求提供我的代码示例,我设法找到了一些旧代码。

    我的文件夹Services中的EmailService.svc之类的服务,编辑如下:

    <%@ ServiceHost Language="C#" Debug="true" 
    Service="Services.IEmailService, Services" 
    Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf"
     %>
    

    在 web.config 中

    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Autofac" publicKeyToken="x" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-3.5.0.0" newVersion="3.5.0.0" />
      </dependentAssembly>
      <dependentAssembly>
    

    AppStart 类

    public static class AppStart
    {
        public static void AppInitialize()
        {
            IContainer container = AutofacContainerBuilder.BuildContainer();
            AutofacHostFactory.Container = container;}
    }
    ...
    

    我将容器分离到另一个类。 不要忘记正确使用 使用 Autofac;

    以及类中设置容器的方法

    public static IContainer BuildContainer()
            {
                var builder = new ContainerBuilder();
                builder.RegisterType<EmailService>().As<IEmailService>();
                return builder.Build();
            }
    

    【讨论】:

    • "...我用行为手动编写了端点。" - 你能为此显示 web.config 吗?
    • 这是几年前的事了。如果我能找到一些我可能仍然拥有的实验室代码,我会在下班回家时看看。在最近的项目中,我使用了 Simple Injector,它应该更快一些,但也更容易弄清楚如何使用,如果你赶时间,我建议你先看看。
    猜你喜欢
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多