ASP.NET MVC 3: как включить определение действия контроллера по URL - PullRequest
2 голосов
/ 13 ноября 2011

Удивлен, я нигде не нахожу этот ответ, как я могу определить, какой контроллер / действие будет вызываться для данного URL в MVC 3?

Обновление

Что я действительно хочузнать: «Как я могу определить, какая ControllerAction будет вызываться для данного URL в MVC 3?».... да

Так что, либо я не знаю о магическом методе, который делает это:

ControllerActionInfo GetControllerActionInfo(string url)

Или мне придется его создатья делаю все, что MVC делает, когда получает запрос http.

Моя цель, чтобы спросить об этом в StackOverflow, состоит в том, что я могу сэкономить время на обратное проектирование этого поведения.Правильный ответ должен выглядеть примерно так:

Here's how you can do it:, и какой-то код будет следовать.

Ответы [ 2 ]

1 голос
/ 13 ноября 2011

Вы должны использовать фиктивные классы HttpContext и HttpRequest следующим образом:

public class DummyHttpRequest : HttpRequestBase {

    private string mUrl;

    public DummyHttpRequest(string url) {
        mUrl = url;
    }

    public override string AppRelativeCurrentExecutionFilePath {
        get {
            return mUrl;
        }
    }

    public override string PathInfo {
        get {
            return string.Empty;
        }
    }

}

public class DummyHttpContext : HttpContextBase {

    private string mUrl;

    public DummyHttpContext(string url) {
        mUrl = url;
    }

    public override HttpRequestBase Request {
        get {
            return new DummyHttpRequest(mUrl);
        }
    }

}

Редактировать: Также вы можете расширить DefaultControllerFactory и добавить простой метод для получения нужной информации вместо экземпляра Controller. ( Примечание: Это просто пример, вы должны поддерживать другие аспекты, такие как ActionNameAttribute и т. Д.)

public class ControllerActionInfo {

    public ControllerActionInfo(Type controllerType, MethodInfo action) {
        ControllerType = controllerType;
        Action = action;
    }

    public Type ControllerType { get; private set; }
    public MethodInfo Action { get; private set; }

}

public class DefaultControllerFactoryEx : DefaultControllerFactory {

    public ControllerActionInfo GetInfo(RequestContext requestContext, string controllerName) {
        Type controllerType = GetControllerType(requestContext, controllerName);

        if (controllerType == null) {
            return null;
        }

        MethodInfo actionMethod = controllerType.GetMethod(requestContext.RouteData.GetRequiredString("action"), BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);

        return new ControllerActionInfo(controllerType, actionMethod);
    }

}

Затем используйте следующий фрагмент кода, чтобы получить доступ к контроллеру:

DummyHttpContext httpContext = new DummyHttpContext("~/home/index");
RouteData routeData = RouteTable.Routes.GetRouteData(httpContext);
// IController controller = new DefaultControllerFactory().CreateController(new RequestContext(httpContext, routeData), routeData.GetRequiredString("controller"));
DefaultControllerFactoryEx controllerFactory = new DefaultControllerFactoryEx();

var result = controllerFactory.GetInfo(new RequestContext(httpContext, routeData), routeData.GetRequiredString("controller"));
0 голосов
/ 13 ноября 2011

Логика для этого в классе System.Web.Mvc.MvcHandler, классе System.Web.Mvc.DefaultControllerFactory и классе System.Web.Mvc.ControllerActionInvoker. .NET Reflector ваш друг.

В основном, структура MVC:

  1. Использует отражение, чтобы получить все контроллеры в проекте приложения.

  2. Тогда он делает что-то вроде IEnumerable<string> controllerNames = controllerTypes.Select(controllerType => controllerType.Name.Replace("Controller",string.Empty));. Затем он пытается сопоставить первый сегмент пути, {controller}, с одним из этих очищенных имен типов контроллеров (без учета регистра).

  3. Затем он просматривает открытые методы этого контроллера, которые имеют тип возвращаемого значения типа ActionResult или некоторую производную. Он сопоставляет имя метода со вторым сегментом пути, {action}, в качестве вызываемого метода действия.

  4. Если выбранный метод имеет параметр с именем id, он сопоставляет третий сегмент пути {id} этому значению и передает его методу. В противном случае необязательный параметр id игнорируется.

  5. Если возвращаемый тип ActionResult является производным от ViewResultBase, тогда IViewEngine пытается найти соответствующее представление в проекте, используя те соглашения, которые были заданы для этого механизма представления. Например, WebFormViewEngine ищет в проекте значения ~/Views/{controller}/{action}.ascx, ~/Views/{controller}/{action}.aspx, ~/Views/Shared/{action}.ascx, ~/Views/Shared/{action}.aspx по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...