WebAPIでAutofacを使用する(フィルタの登録)

9499 ワード

ステップ1:Web APIにAutofacをインストールする.WebApi2 .
誤ってインストールしないでください.Mvc 5も、誤ってAutofacをインストールしないでください.WebApi、AutofacのためWebApiはwebapi 1に与えられています.そうしないと、メンバー「Autofac.Integration.WebApi.AutofacWebApiDependencyResolver.BeginScope()」を書き換えるときに継承セキュリティに違反します.
ステップ2:App_Startでクラスを作成する:AutoFacConfigという名前を付けます.
ステップ3:using Autofacの導入; using Autofac.Integration.WebApi;
namespace WebApi.App_Start
{
    public class AutoFacConfig
    {
        public static void InitAutoFac()
        {
            //    HttpConfiguration.
            var configuration = GlobalConfiguration.Configuration;
            var builder = new ContainerBuilder();

            //     
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).PropertiesAutowired();
            //  :  Autofac      .
            builder.RegisterWebApiFilterProvider(configuration);


            //builder.RegisterType(typeof(MyAuthenticationAttribute)).PropertiesAutowired(); //       MyAuthenticationAttribute   
            var webapiAssembly = Assembly.Load("WebApi");

            //  webapi      IAuthorizationFilter       IActionFilter          
            builder.RegisterAssemblyTypes(webapiAssembly).Where(r => !r.IsAbstract &&
            (typeof(IAuthorizationFilter).IsAssignableFrom(r)) || typeof(IActionFilter).IsAssignableFrom(r)).PropertiesAutowired();


            // Repositorys        IBaseRepository           
            var repository = Assembly.Load("Repositorys");
            builder.RegisterAssemblyTypes(repository).Where(r => !r.IsAbstract).AsImplementedInterfaces().SingleInstance()
               .PropertiesAutowired();


            IContainer container = builder.Build();
            //           Autofac。
            var resolver = new AutofacWebApiDependencyResolver(container);
            configuration.DependencyResolver = resolver;

        }
    }
}

ステップ4:Global.asaxで参照が実行されます.
namespace WebApi
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AutoFacConfig.InitAutoFac();//  InitAutoFac()    
            GlobalConfiguration.Configure(WebApiConfig.Register);
           
        }
    }
}

フィルターに属性注入を使う(特にフィルターの登録に注意し、フィルター対象は直接newではなくIOC容器に取りに行った方が良い、そうでなければフィルターに直接属性注入を使うことはできない)
例えば、認証フィルタを作成しましたが、フィルタに属性依存注入が使用されている場合、このフィルタを登録する際にIOCコンテナからこのフィルタ類オブジェクトのインスタンスを取る必要があり、直接newすることはできません.
namespace WebApi
{
    public class MyAuthenticationAttribute : IAuthorizationFilter//       AuthorizationFilterAttribute
    {
        public IAppInfosRepository app { get; set; }
        public bool AllowMultiple => true;

        public async Task ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func> continuation)
        {
            //       AppKey Sign (        ,            , AppKey Sign        )
            IEnumerable appKeys;
            if (!actionContext.Request.Headers.TryGetValues("AppKey", out appKeys)) //         AppKey
            {
                {
                    return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("     AppKey  ") };
                }
            }
            IEnumerable signs;
            if (!actionContext.Request.Headers.TryGetValues("Sign", out signs)) //         Sign
            {
                return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("     Sign  ") };
            }
            string appKey = appKeys.First();
            string sign = signs.First();
            var appInfo = await app.GetByAppKeyAsync(appKey);//      appinfo    (  AppKey,AppSecret  )
            if (appInfo == null)
            {
                return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("    AppKey") };
            }
            if (appInfo.IsEnable == "true")
            {
                return new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden) { Content = new StringContent("AppKey     ") };
            }

            string requestDataStr = ""; //       
            List> requestDataList = new List>();//       
            if (actionContext.Request.Method == HttpMethod.Post) //   Post  
            {
                //  Post      
                requestDataStr = GetRequestValues(actionContext);
                if (requestDataStr.Length > 0)
                {
                    string[] requestParamsKv = requestDataStr.Split('&');
                    foreach (var item in requestParamsKv)
                    {
                        string[] pkv = item.Split('=');
                        requestDataList.Add(new KeyValuePair(pkv[0], pkv[1]));
                    }
                    //requestDataList    key(     )              
                    requestDataList = requestDataList.OrderBy(kv => kv.Key).ToList();
                    var segments = requestDataList.Select(kv => kv.Key + "=" + kv.Value);//  key=value   
                    requestDataStr = string.Join("&", segments);// &      
                }

            }
            if (actionContext.Request.Method == HttpMethod.Get) //   Get  
            {
                //requestDataList    key(     )                     
                requestDataList = actionContext.Request.GetQueryNameValuePairs().OrderBy(kv => kv.Key).ToList();
                var segments = requestDataList.Select(kv => kv.Key + "=" + kv.Value);//  key=value   
                requestDataStr = string.Join("&", segments);// &      
            }

            //  Sign ( :  requestDataStr+AppSecret md5 )
            string computedSign = MD5Helper.ComputeMd5(requestDataStr + appInfo.AppSecret);

            //     md5           ,            
            if (sign.Equals(computedSign, StringComparison.CurrentCultureIgnoreCase))
            {
                return await continuation();
            }
            else
            {
                return new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("sign    ") };
            }
        }


        /// 
        ///   Post         
        ///     :https://www.cnblogs.com/hnsongbiao/p/7039666.html
        /// 
        /// 
        /// 
        public string GetRequestValues(HttpActionContext actionContext)
        {
            Stream stream = actionContext.Request.Content.ReadAsStreamAsync().Result;
            Encoding encoding = Encoding.UTF8;
            /*
                  StreamReader    ,   dispose,       
                      ,                  
                       using
                using (StreamReader reader = new StreamReader(stream, System.Text.Encoding.UTF8))
                {
                    result = reader.ReadToEnd().ToString();
                }
            */
            var reader = new StreamReader(stream, encoding);
            string result = reader.ReadToEnd();
            /*
                  :   stream.Position = 0;
                      stream       
              request response     Position       ,                    。
            */
            stream.Position = 0;
            return result;
        }
    }
}

WebApiConfig.csクラスにこのフィルタを登録する(統一登録フィルタ)
namespace WebApi
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API      

            // Web API   
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );


            // Autofac IOC     MyAuthenticationAttribute       
            //MyAuthenticationAttribute authorFilter = (MyAuthenticationAttribute)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(MyAuthenticationAttribute));
            //config.Filters.Add(authorFilter); //     

            //  :              ,           ,            IOC                 
            //    new   :    config.Filters.Add(new MyAuthenticationAttribute())
            //          IOC       ,IOC           


            #region        
            var webapiAss = Assembly.Load("WebApi");
            // webapiAss        IAuthorizationFilter  ,     IActionFilter          
            var filters = webapiAss.GetTypes().Where(r => !r.IsAbstract && (typeof(IAuthorizationFilter).IsAssignableFrom(r) || typeof(IActionFilter).IsAssignableFrom(r)));
            foreach (var item in filters)
            {
                // IOC           (          IFilter   ,     IFilter     )
                IFilter filter = (IFilter)GlobalConfiguration.Configuration.DependencyResolver.GetService(item);
                config.Filters.Add(filter); //     
            } 
            #endregion
        }
    }
}