11

Web アプリケーションまたは Windows サービスを介して「WebAPI」Web サイトをホストできるシステムを作成しようとしています。この目的のために、すべてのビジネス ロジックを 1 つのクラス ライブラリに含めて、Windows サービスと "Web" (IIS) サービスの両方でこれを参照できるようにしたいと考えています。

私の現在のアイデアは、HttpSelfHostServer に含まれるセルフ ホスト オプションを使用することです。Web エンドの場合は、標準の webapi Web サイトを作成し、クラス ライブラリへの参照を追加するだけです。

私が見つけたのは、コントローラーが HttpSelfHostServer と同じ名前空間にある場合、正しく動作しますが、コントローラーが外部クラス ライブラリ内にあるとすぐに、サーバーはコントロール/アクションへのルートを解決できなくなることです。

私のコード:

Windows サービス:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Reflection;
using System.IO;

using System.Web.Http.SelfHost;
using System.Web.Http;
using System.Web.Http.Dispatcher;

using WebApiClasses;
using WebApiClasses.Controllers;

namespace WebAPISelfHost
{
    public partial class Service1 : ServiceBase
    {
        private HttpSelfHostServer _server;
        private readonly HttpSelfHostConfiguration _config;
        public const string ServiceAddress = "http://localhost:8080";

        public Service1()
        {
            InitializeComponent();

            _config = new HttpSelfHostConfiguration(ServiceAddress);

            //AssembliesResolver assemblyResolver = new AssembliesResolver();
            //_config.Services.Replace(typeof(IAssembliesResolver), assemblyResolver);

            _config.Routes.MapHttpRoute("DefaultApi",
                "api/{controller}/{id}",
                new { id = RouteParameter.Optional });

        }

        protected override void OnStart(string[] args)
        {
            _server = new HttpSelfHostServer(_config);
            _server.OpenAsync();
        }




        protected override void OnStop()
        {
            _server.CloseAsync().Wait();
            _server.Dispose();
        }
    }

    //public class TestController : ApiController
    //{
    //    public string Get()
    //    {
    //        return "This is an internal test message.";
    //    }
    //}

    class AssembliesResolver : DefaultAssembliesResolver
    {
        public override ICollection<Assembly> GetAssemblies()
        {
            ICollection<Assembly> baseAssemblies = base.GetAssemblies();
            List<Assembly> assemblies = new List<Assembly>(baseAssemblies);

            // Add whatever additional assemblies you wish

            var controllersAssembly = Assembly.LoadFrom(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @"\WebApiClasses.dll");
            baseAssemblies.Add(controllersAssembly);
            return assemblies;
        }
    }
}

コントローラ:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Web.Http;

namespace WebApiClasses.Controllers
{
    public class TestController : ApiController
    {
        public string Get()
        {
            return "hello from class library";
        }
    }
}

「http://localhost:8080/api/」に移動しようとすると、次のようになります。

要求 URI 'http://localhost:8080/api/' に一致する HTTP リソースが見つかりませんでした。「Test」という名前のコントローラーに一致する型が見つかりませんでした。

助言がありますか?私はこれを行うことができるはずだと思います。

4

5 に答える 5

11

この記事をご覧ください http://www.strathweb.com/2012/06/using-controllers-from-an-external-assembly-in-asp-net-web-api/

その中で、コントローラーを含む追加のアセンブリをロードする方法について説明しています。

于 2012-12-19T11:34:34.230 に答える
0

私は最終的にこれを行う方法を見つけ、コードを次のように再配置する必要がありました。

Windowsサービス:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Reflection;
using System.IO;

using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Dispatcher;
using System.Web.Http.SelfHost;

namespace WebAPISelfHost
{
    public partial class Service1 : ServiceBase
    {
        static HttpSelfHostServer CreateHost(string address)
        {
            // Create normal config
            HttpSelfHostConfiguration config = new HttpSelfHostConfiguration(address);

            // Set our own assembly resolver where we add the assemblies we need
            AssembliesResolver assemblyResolver = new AssembliesResolver();
            config.Services.Replace(typeof(IAssembliesResolver), assemblyResolver);

            // Add a route
            config.Routes.MapHttpRoute(
              name: "default",
              routeTemplate: "api/{controller}/{id}",
              defaults: new { controller = "Home", id = RouteParameter.Optional });

            HttpSelfHostServer server = new HttpSelfHostServer(config);
            server.OpenAsync().Wait();

            return server;
        }

        public Service1()
        {
            InitializeComponent();

        }

        protected override void OnStart(string[] args)
        {
            HttpSelfHostServer server = CreateHost("http://localhost:8080");
        }

        protected override void OnStop()
        {
        }
    }

    class AssembliesResolver : DefaultAssembliesResolver
    {
        public override ICollection<Assembly> GetAssemblies()
        {
            ICollection<Assembly> baseAssemblies = base.GetAssemblies();
            List<Assembly> assemblies = new List<Assembly>(baseAssemblies);

            assemblies.Add(Assembly.LoadFrom(@"C:\Users\david.kolosowski\Documents\Visual Studio 2010\Projects\WebAPISelfHost\WebAPISelfHost\bin\Debug\ClassLibrary1.dll"));

            return assemblies;
        }
    }
}

クラスライブラリ:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Web.Http;

namespace ClassLibrary1
{
    public class TestController : ApiController
    {
        public string Get()
        {
            return "hello from class library2";
        }
    }
}

ソリューションにさまざまな構成上の問題があると思うので、すべての参照を削除し、各プロジェクトに必要なものだけを追加しました。

提案を投稿してくれたすべての人に感謝します。

于 2012-12-20T09:23:58.817 に答える
0

将来の読者のために。

別のアセンブリを使用して IIS を使用する方法 (一方向) を次に示します。

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            //routeTemplate: "api/{controller}/{id}",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Http.Dispatcher;

public class MyCustomAssemblyResolver : DefaultAssembliesResolver
{
    public override ICollection<Assembly> GetAssemblies()
    {
        ICollection<Assembly> baseAssemblies = base.GetAssemblies();
        List<Assembly> assemblies = new List<Assembly>(baseAssemblies);
        Type myType = typeof(MyControllerInAnotherAssembly);
        var controllersAssembly = Assembly.GetAssembly(myType );
        baseAssemblies.Add(controllersAssembly);
        return assemblies;
    }
}

および (Global.asax)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Http.Dispatcher;
using System.Web.Security;
using System.Web.SessionState;


public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        WebApiConfig.Register(GlobalConfiguration.Configuration);    
        GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new MyCustomAssemblyResolver());
    }
}
于 2014-12-22T18:56:20.233 に答える