Проблема
Я пытаюсь взять существующее веб-приложение ASP.NET и вручную перенести его на использование MVC 2 (в настоящее время я запускаю RC). Я выполнил несколько шагов (сейчас я перечислю) и, похоже, все заработало, но потом я заметил, что не могу установить AuthorizeAttribute, потому что пользователь имеет значение null на контроллере. Затем я заметил, что когда я перехожу к действию, ни одно из обычных событий жизненного цикла HttpApplication не возникает (например, BeginRequest и т. д.). Я полагаю, что это, вероятно, связано с тем, почему принципал пользователя имеет значение null. Веб-хост — это локальный экземпляр IIS7 (на моей рабочей станции Vista).
Я создал совершенно новое веб-приложение MVC 2, чтобы использовать его в качестве эталона при миграции. Он работает просто отлично, вызывая события приложения и заполняя принципала пользователя, как я и ожидал.
Если вы чувствуете, что хотите наказать себя, читайте все подробности (в меру своих возможностей) ниже.
Этапы миграции
- Убедитесь, что пул приложений для каталога приложений — это .NET 2.0 и интегрированный
- Ссылки на System.Web.Abstractions (v.3.5.0.0), System.Web.routing (v3.5.0.0) и System.Web.Mvc (v2.0.0.0) в моем веб-проекте. Теперь я добавил System.Web.Mvc в качестве локальной ссылки, чтобы упростить интеграцию и развертывание.
- Изменен csproj, чтобы включить надстройку MVC VS (см. эту статью а>)
- В проект добавлены каталоги Controllers и Views, добавленные в /Views/web.config из моего примера приложения MVC.
- Изменил мой web.config (ПРИМЕЧАНИЕ: у меня есть другая хрень в модулях и обработчиках, но я скрыл это для простоты и безопасности... но это вполне может быть частью проблемы):
Раздел compilation:
<compilation defaultLanguage="c#" debug="true">
<assemblies>
<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Data.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
Раздел pages:
<pages enableEventValidation="false"
pageBaseType="MyAssembly.ThemedBasePage">
<controls>
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</controls>
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
</namespaces>
</pages>
The system.webServer/modules section (remember, IIS7 integrated):
<modules>
<remove name="ScriptModule" />
<remove name="UrlRoutingModule" />
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</modules>
Раздел system.webServer/handlers:
<handlers>
<remove name="WebServiceHandlerFactory-Integrated"/>
<remove name="ScriptHandlerFactory"/>
<remove name="ScriptHandlerFactoryAppServices"/>
<remove name="ScriptResource"/>
<remove name="MvcHttpHandler"/>
<remove name="UrlRoutingHandler"/>
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</handlers>
Обновлен мой global.asax для регистрации маршрутов и игнорирования вещей, которые мешали бы моим устаревшим вещам:
private static void RegisterRoutes(RouteCollection routes) { // place any routes here you need to ignore, whether they // be legacy or legitimate resources. routes.IgnoreRoute(""); // i currently have functionality at "/", and this route frees up the root to be used by my Default.aspx routes.IgnoreRoute("{webForms}.aspx/{*pathInfo}"); routes.IgnoreRoute("{webServices}.asmx/{*pathInfo}"); routes.IgnoreRoute("ajaxpro/{*pathInfo}"); routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new {controller = "Home", action = "Index", id = ""} // Parameter defaults ); } protected void Application_Start() { // legacy crap here AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); }
Дополнительная информация
Я также использую последнюю версию Autofac (v1.4.5.676) и их обработчики веб-интеграции. Я проверил оба способа: все автофакты полностью удалены/отключены и все настроено так, как я хочу; никак не влияет на проблему в любом случае.
Я также пробовал это с моими специализированными супер-сладкими настройками IgnoreRoute и без них. Нет эффекта.
Кроме того, я хотел бы прояснить, что маршруты, похоже, работают, я правильно отправляюсь к своим контроллерам и действиям, у меня просто есть нулевой принцип в HttpContext.Current.User, и, похоже, он совершенно не увеличивает жизненный цикл приложения. Мероприятия. Если бы мне не нужно было, знаете ли, получать текущего принципала или делать какие-то надоедливые авторизации, я бы никогда не узнал, что что-то не так ;)
И да, обычные страницы ASPX работают правильно, и события жизненного цикла приложения вызываются нормально.
Вот пример простого тестового контроллера, который я сделал, но он не работает:
[Authorize]
public class FartsController : Controller
{
//
// GET: /Farts/
public ActionResult Index()
{
return View();
}
}
что приводит к следующему исключению:
[NullReferenceException: Object reference not set to an instance of an object.]
System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(HttpContextBase httpContext) +48
System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext) +35
System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor) +103
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +316
System.Web.Mvc.Controller.ExecuteCore() +104
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +36
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__4() +34
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +53
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +43
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +7
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8678910
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
Это отстой :(. Спасибо, что прочитали мой рассказ.