Я попробовал две вещи.В каждом случае общий контроллер и представления были расположены в отдельной сборке.Для подтверждения концепции я реализовал общую обработку ошибок приложения.Поэтому в моем приложении Mvc3 для конечной точки global.asax реализует:
protected void Application_Error()
{
ApplicationErrorHandler.Get().Handle(Server, new HttpResponseWrapper(Response), new HttpContextWrapper(Context));
}
Где обработчик ошибок приложения реализован в отдельной сборке:
public class ApplicationErrorHandler
{
public static ApplicationErrorHandler Get()
{
return new ApplicationErrorHandler();
}
public void Handle(HttpServerUtility server, HttpResponseBase response, HttpContextBase context)
{
var exception = server.GetLastError();
var httpException = exception as HttpException;
response.Clear();
server.ClearError();
var routeData = new RouteData();
routeData.Values["controller"] = "Errors";
routeData.Values["action"] = "Http500";
routeData.Values["exception"] = exception;
response.StatusCode = 500;
if (httpException != null)
{
response.StatusCode = httpException.GetHttpCode();
switch (response.StatusCode)
{
case 403:
routeData.Values["action"] = "Http403";
break;
case 404:
routeData.Values["action"] = "Http404";
break;
}
}
IController errorsController = new ErrorsController();
var rc = new RequestContext(context, routeData);
errorsController.Execute(rc);
}
}
В этой же сборке находится в папке Controllers.ErrorsController и Views \ Errors содержит 3 необходимых представления;Http403.cshtml, Http404.cshtml и Http405.cshtml.Таким образом, структура такая же, как в вашем обычном проекте Mvc3.Однако для того, чтобы получить поддержку @model и intelisense для работы, вам также понадобится web.config - копия файла из Views в вашем обычном проекте и размещенная под views в этой отдельной сборке.
Когда, скажем, приложениеВ нашем приложении возникает ошибка (http status 500 - внутренняя ошибка сервера), выполняется ErrorsController, и представлением, используемым в этом случае, будет Http500.cshtml.Рассматриваемый путь будет:
- ~ \ Views \ Errors \ Http500.cshtml
- ~ \ View \ Shared \ Http500.cshtml
InДля того, чтобы предоставить файл из сборки, я попробовал две вещи:
Подход первый: реализовать VirtualPathProvider.Я не буду вдаваться в подробности, но цель состоит в том, чтобы встроить представления cshtml в качестве ресурсов и обработать их с помощью VirtualPathProvider и VirtualFile.Проблема с этим подходом заключается в том, что я не нашел подходящего способа также сервировать web.config из папки Views, чтобы Razor мог оценить представление.Я мог бы получить его для извлечения файла и его потоковой передачи, но не для его выполнения.Чтобы объяснить причину проблемы, рассмотрим файл Http500.cshtml:
@model Exception
<h3>@MvcHtmlString.Create(Model.Message.Replace(Environment.NewLine, "<br />").Replace("\t", " "))</h3>
<p>@MvcHtmlString.Create(Model.StackTrace.Replace(Environment.NewLine, "<br />").Replace("\t", " "))</p>
<input type="hidden" name="serverError" value="true"/>
. Было возвращено содержимое файла, а не оцененное исключение.Причина в том, что также необходимо обслужить файл web.config из папки View, чтобы использовать Razor.По умолчанию механизм просмотра - это веб-формы (.aspx).
Второй подход: создать виртуальный каталог в IIS.Этот подход работает намного лучше, потому что представления не должны быть скомпилированы как ресурсы, нет необходимости в виртуализации.Все, что нужно, это создать виртуальный каталог Ошибки в папке Views в моем конечном приложении и указать его, где развернуты Views \ Errors из общей сборки.
Конечно, он не ведет себя как правильный плагин, потому чтообщие файлы должны быть развернуты отдельно от .dll, но меня это не слишком беспокоит.
Однако, если кто-то знает, как заставить виртуальные файлы работать на Razor, я весь в ушах.Хорошо - все глаза действительно.