WebApi 2 AssemblyResolver

时间:2017-04-17 16:23:24

标签: c# .net asp.net-web-api

我在WebApi 2.0中创建了一个包含所有控制器的控制器程序集,并按照本文 - https://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/创建了一个CustomAssemblyResolver并添加了代码以替换Application_Start中的程序集解析程序。这是我的代码的样子:

My CustomAssemblyResolver:

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

        string thirdPartySource = "C:\\Research\\ExCoWebApi\\ExternalControllers";

        if (!string.IsNullOrWhiteSpace(thirdPartySource))
        {
            if (Directory.Exists(thirdPartySource))
            {
                foreach (var file in Directory.GetFiles(thirdPartySource, "*.*", SearchOption.AllDirectories))
                {
                    if (Path.GetExtension(file) == ".dll")
                    {
                        var externalAssembly = Assembly.LoadFrom(file);

                        baseAssemblies.Add(externalAssembly);
                    }
                }
            }
        }
        return baseAssemblies;
    }
}

我的Application_Start:

    protected void Application_Start()
    {
        Debugger.Launch();

        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new CustomAssemblyResolver());            


    }

如您所见,我用CustomAssemblyResolver替换默认的程序集解析器。

以下是我如何注册到第三方控制器的路线:

    public static void RegisterRoutes(RouteCollection routes)
    {            
        routes.MapHttpRoute(
            name: "Test",
            routeTemplate: "api/thirdparty/math",
            defaults: new { controller = "Math" }
        );            
    }

这就是我的MathController看起来像是一个单独的程序集:

public class MathController : ApiController
{
    [HttpPost]
    public int AddValues(MathRequest request)
    {
        int response = MathOperations.Add(request.Value1, request.Value2);
        return response;
    }
}

这是我通过邮递员点击的端点:http://localhost/ExCoWebApi/api/thirdparty/math在主体中使用POST操作和MathRequest JSON字符串,这就是我得到的响应:

{   &#34;消息&#34;:&#34;未找到与请求URI匹配的HTTP资源&#39; http://localhost/ExCoWebApi/api/thirdparty/math&#39;。&#34;,   &#34; MessageDetail&#34;:&#34;没有找到与名为&#39; Math&#39;。&#39;。&#34;的数字控制器相匹配的类型。 }

调试后我发现AssemblyResolver确实在Application Start中被CustomAssemblyResolver取代,但问题是CustomAssemblyResolver的GetAssemblies()方法没有被调用。因此,包含MathController的程序集无法加载。

我在这里缺少什么?

修改

在拼命寻找解决方案的过程中,我提出了一种测试方法,在其中构建自己的HttpConfiguration对象并替换其中的AssemblyResolver,它就像一个魅力!来自CustomAssemblyResolver的GetAssemblies()函数被调用,我能够调用我的外部控制器。我想知道从&#34; GlobalConfiguration.Configuration&#34返回的HttpConfiguration对象是否存在差异。 ;与手动实例化..对此的任何帮助将不胜感激。这是我的测试方法的代码:

    [TestMethod]
    public void TestExternalControllerCall()
    {
        try
        {
            HttpClient client = GetClient();
            MathRequest mathReq = new MathRequest { Value1 = 10, Value2 = 20 };
            var response = client.PostAsJsonAsync(string.Concat("http://localhost/api/thirdparty/math"), mathReq).Result;
            var entResponse = response.Content.ReadAsAsync<int>().Result;
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
        }
    }

    private HttpClient GetClient()
    {            
        HttpConfiguration config = new HttpConfiguration();
        config.Routes.MapHttpRoute(
            name: "Test",
            routeTemplate: "api/thirdparty/math",
            defaults: new { controller = "Math" }
        );
        config.Services.Replace(typeof(IAssembliesResolver), new CustomAssemblyResolver());
        HttpServer server = new HttpServer(config);
        HttpClient client = new HttpClient(server);
        return client;        
    }

1 个答案:

答案 0 :(得分:1)

发现问题:

没有调用GetAssemblies()的原因是因为为GlobalConfiguration.Configure设置的回调方法(WebApiConfig.Register)正在调用&#34; config.MapHttpAttributeRoutes();&#34;。

GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver),new CustomAssemblyResolver());

代码实际上属于GlobalConfiguration.Configure中配置的回调方法,而不是Global.asax,如果你有为GlobalConfiguration.Configure设置的回调。所以我将IAssemblyResolver替换语句移到了WebApiConfig中的Register方法:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Services.Replace(typeof(IAssembliesResolver), new CustomAssemblyResolver());

        // Web API routes
        config.MapHttpAttributeRoutes();            
    }
}