none
Web form啟用routing, 自訂的HttpHandler無法作用... RRS feed

  • 問題

  • 大家好..

    小弟想試著用webform學習autofac去"注入物件"...

    但是被Webform的routing折騰得很久...

    我參考了.NET 相依性注入這本電子書的web form注入部分(p146)...

    Global.asax

    void Application_Start(object sender, EventArgs e)
            {
                // Code that runs on application startup
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
                var builder = new ContainerBuilder();
                builder.RegisterType<ProductService>().As<IProductService>();
                builder.RegisterType<CategoryService>().As<ICategoryService>();
                Application["Container"] = builder.Build();
            }

    然後..

    public class AutofacPageHandlerFactory : PageHandlerFactory
        {
            public override IHttpHandler GetHandler(HttpContext context, string requestType, string virtualPath, string path)
            {
                var page = base.GetHandler(context, requestType, virtualPath, path) as Page;
                if (page == null)
                    return null;
                // end if
                var container = context.Application["Container"] as IContainer;
                if (container != null)
                {
                    container.InjectProperties(page);
                } // end if
                return page;
            }
        }

    接下來在web.config設定httphandler..

    <handlers>
          <add name="AutofacPageHandlerFactory" path="*.aspx" verb="*" type="WA_RespositoryTest.Misc.AutofacPageHandlerFactory"/>
        </handlers>

    結果測試的時候踢到鐵板...

    routing啟用的情況下, 這個自訂的HttpHandler沒有任何動作....

    變成從網頁取得注入元件都是null...

    搞了很久搞不定, 找谷哥大神求救查不到有甚麼解法....

    請問有甚麼辦法可以routing被啟用時, 也可以讓自訂的HttpHandler作用?...


    • 已編輯 StoRAID 2016年12月20日 下午 02:11
    2016年12月20日 下午 01:32

解答

  • 努下做了一下功課...

    慢慢求教谷歌大神一頁一頁爬....

    問題已解決, 已成功注入...

    使用routing後, 要跳到routehandler處理...

    自訂測試用的routehandler(內容還是仿照蔡老師的範例)

    public class CustTestRouteHandler : IRouteHandler
        {
            public string VirtualPath { get; private set; }
    
            public CustTestRouteHandler(string virtualPath)
            {
                this.VirtualPath = virtualPath;
            }
            public IHttpHandler GetHttpHandler(RequestContext requestContext)
            {
                var page = BuildManager.CreateInstanceFromVirtualPath(this.VirtualPath, typeof(Page)) as IHttpHandler;
                var cxt = requestContext.HttpContext;
                var container = cxt.Application["Container"] as IContainer;
                if (container != null)
                {
                    container.InjectProperties(page);
                } // end if
                return page;
            }
        }

    RouteConfig將自訂的rouehandler加入至路由:

    public static void RegisterRoutes(RouteCollection routes)
            {
                var settings = new FriendlyUrlSettings();
                settings.AutoRedirectMode = RedirectMode.Permanent;
                
    
                var custRoute = new Route("Test/Default/", new CustTestRouteHandler("~/Test/Default.aspx"));
                routes.Add("TestDefault", custRoute);
                routes.EnableFriendlyUrls(settings);
            }

    Global.asax

    void Application_Start(object sender, EventArgs e)
            {
                // Code that runs on application startup
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
                var builder = new ContainerBuilder();
                builder.RegisterType<TestService>().As<ITestService>();
    
                Application["Container"] = builder.Build();
            }

    根據路由對應的測試頁面(Property Injection):

     public partial class Default : System.Web.UI.Page
        {
    
            public ITestService Service { get; set; }
            protected void Page_Init(object sender, EventArgs e)
            {
                this.Service.Value = DateTime.Now.ToString();
            }
    
            protected void Page_Load(object sender, EventArgs e)
            {
                
            }
        }

    from MS:

    https://msdn.microsoft.com/en-us/library/cc668202.aspx

    不要折騰的話, 還是乖乖用官方的方案...

    http://docs.autofac.org/en/latest/integration/webforms.html



    • 已編輯 StoRAID 2016年12月21日 上午 11:01
    • 已標示為解答 StoRAID 2016年12月22日 上午 02:04
    2016年12月21日 上午 10:37

所有回覆

  • 您可以參考這篇討論的做法:

    Autofac Property Injection is always null

    2016年12月21日 上午 01:09
  • 您可以參考這篇討論的做法:

    Autofac Property Injection is always null

    感謝您的回覆..

    可能我表達不清楚..

    這是我網頁代碼:

    public IProductService Service { get; set; }
    
            protected void Page_Load(object sender, EventArgs e)
            {
                if (!IsPostBack)
                    Session.Clear();
                // end if
            }
    
            public IList<Models.Product> GetAll()
            {
                return this.Service.GetAll().ToList();
            }
    
            protected void BtnFind_Click(object sender, EventArgs e)
            {
                var id = 0;
                int.TryParse(Request["txtId"], out id);
                var d1 = this.Service.GetByID(id);
                Session["model"] = d1;
            }
    Service物件一直獲取為null...

    我按照蔡老師的範例..

    想透過執行中的自訂httphandler注入屬性到目前執行的page..
    然後頁面中的Service屬性就可以直接獲取注入的相關物件..
    只是這個自訂httphandler, 我發現他沒有執行..

    故意在裡面加入例外也沒有作用(沒有任何從自訂httphandler的例外拋出..)...
    雖然這跟autofac沒甚麼關係...

    不要使用ASP.NET的routing機制, 自訂的httphandler會正常執行...
    我查不到為什麼會這樣...

    所以才想問一下是否routing運作時, 透過web.config註冊的自訂httphandler是否有辦法可以正常執行...



    • 已編輯 StoRAID 2016年12月21日 上午 03:54
    2016年12月21日 上午 03:53
  • 看看有沒有幫助
    http://stackoverflow.com/questions/589374/how-to-use-dependency-injection-with-asp-net-web-forms

    微軟免費線上課程

    HTML5 & JavaScript程式開發實戰(MyBook)

    開發ASP.NET您要瞭解的基楚

    http://www.dotblogs.com.tw/ian (MyBlog)

    2016年12月21日 上午 06:09
    版主
  • 看看有沒有幫助
    http://stackoverflow.com/questions/589374/how-to-use-dependency-injection-with-asp-net-web-forms

    微軟免費線上課程

    HTML5 & JavaScript程式開發實戰(MyBook)

    開發ASP.NET您要瞭解的基楚

    http://www.dotblogs.com.tw/ian (MyBlog)

    感謝您的回覆...

    先不管autofac, 我故意寫一個HttpHandler...

    namespace WA_ActiveHttpHandlerWithRoutingTest.Handlers
    {
        public class CustTestPageHandler : PageHandlerFactory
        {
            public CustTestPageHandler()
            {
                throw new Exception("CustTestPageHandler");
            }
    
            public override IHttpHandler GetHandler(HttpContext context, string requestType, string virtualPath, string path)
            {
                return base.GetHandler(context, requestType, virtualPath, path);
            }
        }
    }

    這個handler在初始化的時候就會引發例外...

    把這個handler註冊到web.config

    <handlers>
          <add name="CustTestPageHandler" path="*" verb="*" type="WA_ActiveHttpHandlerWithRoutingTest.Handlers.CustTestPageHandler"/>
        </handlers>

    隨便新增一個頁面...

    沒有routing的情況下: 

    http://localhost:36769/Test/Default.aspx

    這個自訂的httphandler初始化的例外會被成功引發...

    Line 11:         public CustTestPageHandler()
    Line 12:         {
    Line 13:             throw new Exception("CustTestPageHandler");
    Line 14:         }
    Line 15: 

    用routing之後:

    http://localhost:36769/Test/Default

    自訂的httphandler初始化的例外沒有被引發, 感覺就是這個handler沒有運作...

    小弟現在就是卡在這...

    web form的情況下, 不知道routing使用的情況下, 有沒有辦法和httphandler一起使用..

    我看stackoverflow有老外猜測是這樣:

    Looks like the default RouteHandler picked up in this case and used it's own pipeline to handle the page creation. If you want to do this you should not restrict your handle to .aspx pages.

    • 已編輯 StoRAID 2016年12月21日 上午 09:02
    2016年12月21日 上午 09:02
  • 努下做了一下功課...

    慢慢求教谷歌大神一頁一頁爬....

    問題已解決, 已成功注入...

    使用routing後, 要跳到routehandler處理...

    自訂測試用的routehandler(內容還是仿照蔡老師的範例)

    public class CustTestRouteHandler : IRouteHandler
        {
            public string VirtualPath { get; private set; }
    
            public CustTestRouteHandler(string virtualPath)
            {
                this.VirtualPath = virtualPath;
            }
            public IHttpHandler GetHttpHandler(RequestContext requestContext)
            {
                var page = BuildManager.CreateInstanceFromVirtualPath(this.VirtualPath, typeof(Page)) as IHttpHandler;
                var cxt = requestContext.HttpContext;
                var container = cxt.Application["Container"] as IContainer;
                if (container != null)
                {
                    container.InjectProperties(page);
                } // end if
                return page;
            }
        }

    RouteConfig將自訂的rouehandler加入至路由:

    public static void RegisterRoutes(RouteCollection routes)
            {
                var settings = new FriendlyUrlSettings();
                settings.AutoRedirectMode = RedirectMode.Permanent;
                
    
                var custRoute = new Route("Test/Default/", new CustTestRouteHandler("~/Test/Default.aspx"));
                routes.Add("TestDefault", custRoute);
                routes.EnableFriendlyUrls(settings);
            }

    Global.asax

    void Application_Start(object sender, EventArgs e)
            {
                // Code that runs on application startup
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
                var builder = new ContainerBuilder();
                builder.RegisterType<TestService>().As<ITestService>();
    
                Application["Container"] = builder.Build();
            }

    根據路由對應的測試頁面(Property Injection):

     public partial class Default : System.Web.UI.Page
        {
    
            public ITestService Service { get; set; }
            protected void Page_Init(object sender, EventArgs e)
            {
                this.Service.Value = DateTime.Now.ToString();
            }
    
            protected void Page_Load(object sender, EventArgs e)
            {
                
            }
        }

    from MS:

    https://msdn.microsoft.com/en-us/library/cc668202.aspx

    不要折騰的話, 還是乖乖用官方的方案...

    http://docs.autofac.org/en/latest/integration/webforms.html



    • 已編輯 StoRAID 2016年12月21日 上午 11:01
    • 已標示為解答 StoRAID 2016年12月22日 上午 02:04
    2016年12月21日 上午 10:37