本帖最后由 zhuanshen712 于 2011-02-22 11:04:08 编辑

解决方案 »

  1.   

    #throw new ArgumentException("rowCount must be zero when pageCount is zero");
      

  2.   

    确实是这样啊
    #throw new ArgumentException
      

  3.   

    你大爷的,哥好不容易发个帖子,居然赶上csdn维护.我说怎么这么长时间没人回复呢.
      

  4.   

    csdn出问题了?JF   
      

  5.   

    不知道楼主为什么发问,因为楼主把源码看的很好了。MvcHandler 是一个 IHttpHandler,他是由 IRouteHandler.GetHttpHandler 返回的,MvcRouteHandler 是 Global.asax 里 MapRoute 时 IRouteHandler 的默认值,如果不使用 MapRoute,则可以使用 Route 的构造函数,传递自定义的 IRouteHandler。整个过程如下:收到请求
    UrlRoutingModule
    MvcRouteHandler (IRouteHandler)
    MvcHandler (IHttpHandler)
    ...
    Controller.Action
      

  6.   

    mvc不是也要走application在BuildSteps里面的各个步骤么?
    既然是这样,那么它是怎么具体得到mvchandler的呢?
    以前版本的,我能看懂,因为它在调用handler.processrequest之前,更改了handler。
    而之后的版本,去掉了PostMapRequestHandler,所以,它就是按照默认的请求流程,通过HttpApplication.MapHandlerExecutionStep(app))得到handler的,在这个里面,它通过调用IHttpHandlerFactory factory = this.GetFactory(mapping);来得到handler。但是这个,不是通过例如PageHandlerFactory等来得到具体的handler的吗?而mvc,有这个factory吗?因为这个步骤,我理解的肯定是要走的,而我看MapHandlerExecutionStep里面也没有routHandler.getHandler啊??
    倒是有
     HttpHandlerAction mapping = this.GetHandlerMapping(context, requestType, path, useAppConfig);
    ........
    IHttpHandlerFactory factory = this.GetFactory(mapping);
    ........
     factory.GetHandler(....)
    ....
    等这样的代码。难道这个里面就能获得mvchandler吗?
    还是微软对这个dll也进行了修改或扩展?使得这个工厂可以获得mvchandler???还请指教。
      

  7.   

    20楼的兄弟,如你所说:
    UrlRoutingModule
    MvcRouteHandler (IRouteHandler)
    MvcHandler (IHttpHandler)
    ...我看UrlRoutingModule里面的代码时,版本1的,我可以理解,但是版本2(v4.0)的就不能理解了
    因为版本1:是在application事件中按照webform的流程,得到handler后,将这个handler修改为了mvchandler(见代码段2 context.Handler = data.HttpHandler;)
    但是版本2呢?它将修改handler的事件没有在UrlRoutingModule中进行拦截。而是通过在application获得handler之前的事件(PostResolveRequestCache)中通过
    IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
    context.RemapHandler(httpHandler);
    进行了可能对handler的修改,但是,即便是这样的话,在执行application的步骤MapHandlerExecutionStep的时候,又做了些什么事情呢??实在是困扰。
      

  8.   

    我对mvc源码还没有楼主熟悉,这里有个文章,Understanding the MVC Application Execution Process,楼主看看有帮助没http://www.asp.net/mvc/tutorials/understanding-the-asp-net-mvc-execution-process-cs
      

  9.   

    UrlRoutingModule module 使用 RouteTable 里第一个匹配的 Route,Route 有一个 RouteHandler 属性,默认情况返回的是 MvcRouteHandler,剩下的你都知道了。我在 mvc 2 的源码里没找到 IHttpHandlerFactory 的引用
      

  10.   

    在这篇文章,我注意到: If no routes match, the UrlRoutingModule object does nothing and lets the request fall back to the regular ASP.NET or IIS request processing.
    那可不可以这么想:如果有route匹配了,就不回到正常的 ASP.NET or IIS request processing了吗???
    难道routing会改变asp.net的正常请求过程么?这会吗???
      

  11.   

    请求进来,UrlRoutingModule 会得到处理这个请求的机会,如果有和请求匹配的 Route,则由这个 Route 的 RouteHandler 处理,没有匹配的话,则回退到普通的asp.net IHttpHandler,比如 aspx 扩展名对应 Page 类。如果也没有对应的 IHttpHandler,则回退到 IIS 的处理过程,比如一个 html 页面,直接向浏览器返回文件内容,或者 404 错误。
      

  12.   

    额,RouteHandler会得到MvcRouteHandler,我了解。我所不明白的是这个:每个请求,都会经过application的各个事件吧?
    ...
    app.CreateEventExecutionSteps(HttpApplication.EventBeginRequest, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventAuthenticateRequest, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventDefaultAuthentication, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventPostAuthenticateRequest, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventAuthorizeRequest, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventPostAuthorizeRequest, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventResolveRequestCache, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventPostResolveRequestCache, steps);
        steps.Add(new HttpApplication.MapHandlerExecutionStep(app));    app.CreateEventExecutionSteps(HttpApplication.EventPostMapRequestHandler, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventAcquireRequestState, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventPostAcquireRequestState, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventPreRequestHandlerExecute, steps);
        steps.Add(new HttpApplication.CallHandlerExecutionStep(app));    app.CreateEventExecutionSteps(HttpApplication.EventPostRequestHandlerExecute, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventReleaseRequestState, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventPostReleaseRequestState, steps);
        steps.Add(new HttpApplication.CallFilterExecutionStep(app));
        app.CreateEventExecutionSteps(HttpApplication.EventUpdateRequestCache, steps);
        app.CreateEventExecutionSteps(HttpApplication.EventPostUpdateRequestCache, steps);
    ....也就是说,mvc得到mvchandler也会通过这些步骤去得到。在这些步骤中,红色字体是得到handler,蓝色字体是执行handler.processrequest。
    mvc也要经过这两步吧?在UrlRoutingModule中,也是注册了application的事件去对handler进行修改的。
    版本1在得到handler(红色字体)之后,对handler进行了修改,修改为了mvchandler。这样在执行handler的时候,自然是mvchandler.processrequest
    版本2没有了在handler(红色字体)后的事件注册,也就是没有对handler进行修改。难道新版本在得到handler(红色字体)的时候,就已经是mvchandler了吗?
      

  13.   

    http://msdn.microsoft.com/en-us/library/dd381612.aspx
      

  14.   

    按说,应该是application中各个步骤都会执行完成,才算是一个请求结束吧?
      

  15.   

    楼主的疑问似乎是和 4.0 引入新的 UrlRoutingHandler 有关,http://msdn.microsoft.com/zh-cn/vbrun/system.web.routing.urlroutinghandler
      

  16.   

    刚刚看了看application的MapHttpHandler,有很大的修改.可能是在这儿....
      

  17.   

    protected virtual void Init(HttpApplication application)
    {
        if (application.Context.Items[_contextKey] == null)
        {
            application.Context.Items[_contextKey] = _contextKey;
            application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
        }

    public virtual void PostResolveRequestCache(HttpContextBase context)
    {
        RouteData routeData = this.RouteCollection.GetRouteData(context);
        if (routeData != null)
        {
            IRouteHandler routeHandler = routeData.RouteHandler;
            if (routeHandler == null)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
            }
            if (!(routeHandler is StopRoutingHandler))
            {
                RequestContext requestContext = new RequestContext(context, routeData);
                context.Request.RequestContext = requestContext;
                IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
                if (httpHandler == null)
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), new object[] { routeHandler.GetType() }));
                }
                if (httpHandler is UrlAuthFailureHandler)
                {
                    if (!FormsAuthenticationModule.FormsAuthRequired)
                    {
                        throw new HttpException(0x191, SR.GetString("Assess_Denied_Description3"));
                    }
                    UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
                }
                else
                {
                    context.RemapHandler(httpHandler);
                }
            }
        }
      

  18.   

    这句:
    IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);和这句:
    context.RemapHandler(httpHandler);
      

  19.   

    这个是 remap handler 的实现public void RemapHandler(IHttpHandler handler)
    {
        IIS7WorkerRequest request = this._wr as IIS7WorkerRequest;
        if (request != null)
        {
            if (this._notificationContext.CurrentNotification >= RequestNotification.MapRequestHandler)
            {
                throw new InvalidOperationException(SR.GetString("Invoke_before_pipeline_event", new object[] { "HttpContext.RemapHandler", "HttpApplication.MapRequestHandler" }));
            }
            string handlerType = null;
            string handlerName = null;
            if (handler != null)
            {
                Type type = handler.GetType();
                handlerType = type.AssemblyQualifiedName;
                handlerName = type.FullName;
            }
            request.SetRemapHandler(handlerType, handlerName);
        }
        this._remapHandler = handler;
    }  
      

  20.   

    兄弟谢谢了...
    你看这个帖子问题的最下面我写的:...
    我看到,在context.RemapHandler(httpHandler)中,有this._remapHandler = handler;而在获取handler的时候,也就是在MapHandlerExecutionStep中获得handler的时候,代码中有:
     IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;
      using (new ApplicationImpersonationContext())
      {
      if (handler != null)
      {
      return handler;
      }
      ..............这个里面也同样有得到RemapHandlerInstance 的代码,难道是它吗?
    也就是说,过程难道是这样??
    1:在MapHandlerExecutionStep之前,更改httpcontext,并设置mvchandler为context的某个属性[先这样说,不一定正确]
    2:正常的调用MapHandlerExecutionStep,提取之前的context某个属性,从而获得mvchandler
    [这一步,由于第2步得到的已经是mvchandler,所以这步没有了,也就是没有了注册PostMapRequestHandler的方法 3:更改第二步的handler为mvchandler]
    4:调用CallHandlerExecutionStep,从而调用mvchandler.processrequest就是这里不明白啊....
      

  21.   

    context.RemapHandler(httpHandler) 之后,context.RemapHandlerInstance 就不为 null 了,这是另个函数,有一句是 httpContext.Handler = httpContext.RemapHandlerInstance;。种种迹象表明,application 会检查 context.RemapHandlerInstance 属性,如果它不为 null,他就是要用的 http handlervoid HttpApplication.IExecutionStep.Execute()
    {
        HttpContext httpContext = this._application.Context;
        HttpRequest request = httpContext.Request;
        IHttpHandler handler = null;
        string managedHandlerType = null;
        if (EtwTrace.IsTraceEnabled(5, 1))
        {
            EtwTrace.Trace(EtwTraceType.ETW_TYPE_MAPHANDLER_ENTER, httpContext.WorkerRequest);
        }
        IIS7WorkerRequest workerRequest = httpContext.WorkerRequest as IIS7WorkerRequest;
        if (httpContext.RemapHandlerInstance != null)
        {
            httpContext.Handler = httpContext.RemapHandlerInstance;
        }
        // 这里省略1万字
    }
      

  22.   

    在 reflector 里找到 IExecutionStep,点 Derived Types,选 MaterializeHandlerExecutionStep
      

  23.   

    我查了一下,Materialize 的意思是:具体化;成为现实
      

  24.   

    强啊兄弟,可是这个步骤MaterializeHandlerExecutionStep是啥时候执行的呢?
    我得再找找....
      

  25.   

    不能说是啥时候执行的,是MaterializeHandlerExecutionStep是啥时候加入application的ExecuteSteps中的呢...
      

  26.   

    果然正点,原来就是这个.
    我查找了v2.0的dll,相比v4.0的dll,就少了这些:
    if (httpContext.RemapHandlerInstance != null)
        {
            httpContext.Handler = httpContext.RemapHandlerInstance;
        }
    而这些,正好是UrlRouteModule里面存入的mvcHandler.怪不得v4.0版本的UrlRouteModule不用在CallHandlerExecutionStep之前注册PostMapRequestHandler事件去修改handler了呢...哈哈.
    多谢兄弟了.就是还有一个小问题比较遗憾,还不知道这个MaterializeHandlerExecutionStep是啥时候加入application的ExecuteSteps中的...
      

  27.   

    楼主真是好学,私信发个QQ,交个朋友
    HttpApplication+PipelineStepManager 类的 BuildSteps 函数internal override void BuildSteps(WaitCallback stepCallback)
    {
        HttpApplication app = base._application;
        HttpApplication.IExecutionStep step = new HttpApplication.MaterializeHandlerExecutionStep(app);
        app.AddEventMapping("ManagedPipelineHandler", RequestNotification.MapRequestHandler, false, step);
        HttpApplication.IExecutionStep step2 = new HttpApplication.CallHandlerExecutionStep(app);
        app.AddEventMapping("ManagedPipelineHandler", RequestNotification.ExecuteRequestHandler, false, step2);
        HttpApplication.IExecutionStep step3 = new HttpApplication.CallFilterExecutionStep(app);
        app.AddEventMapping("AspNetFilterModule", RequestNotification.UpdateRequestCache, false, step3);
        app.AddEventMapping("AspNetFilterModule", RequestNotification.LogRequest, false, step3);
        this._resumeStepsWaitCallback = stepCallback;
      

  28.   

    我关注的问题和楼主的一样,目前我只是找到了这:
        internal class PipelineStepManager : HttpApplication.StepManager
        {
            // Fields
            private WaitCallback _resumeStepsWaitCallback;
            private bool _validateInputCalled;
            private bool _validatePathCalled;        // Methods
            [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
            internal PipelineStepManager(HttpApplication app) : base(app)
            {
            }        internal override void BuildSteps(WaitCallback stepCallback)
            {
                HttpApplication app = base._application;
                HttpApplication.IExecutionStep step = new HttpApplication.MaterializeHandlerExecutionStep(app);
                app.AddEventMapping("ManagedPipelineHandler", RequestNotification.MapRequestHandler, false, step);
       //此处省略
      
            }
      

  29.   

    楼主其实已经找到答案了:
     IHttpHandler handler = (context.ServerExecuteDepth == 0) ? context.RemapHandlerInstance : null;