Как моделировать Сервер. Передача в ASP.NET MVC?

TL; DR

blockquote>

__proto__ является свойством object, которое позволяет вам искать в цепочке прототипов. В то время как prototype является свойством Function, которое позволяет вам добавлять общие функции в функцию конструктора.

Длинный ответ

blockquote>

Поймите это на примере, скажем, вы создаете функцию конструктора.

function A() {}, а затем создать его экземпляр, var a = new A().

Затем добавьте функцию следующим образом:

A.prototype.getA = function () { return 'A'; }.

Теперь, если вы попытаетесь получить доступ к a.getA(), вы получите результат, то есть getA будет выполнено.

Но как он узнает о функции getA, хотя getA был добавлен после создания экземпляра a. Именно из-за использования __proto__ вы можете перемещаться вверх по цепочке (вы, наверное, слышали о цепочке прототипов).

Технически, __proto__ является свойством объекта, тогда как prototype является свойством function. Но как functions мог иметь собственность? Потому что все в JavaScript неявно преобразуется в объект. Вы никогда не задумывались, как вы могли что-то вроде этого: 'test'.toUpperCase()? Разве строковые литералы не являются «объектами» и являются ли они примитивами?

Прочитайте это для справки: http://jayendra.co.in/objects-in-javascript/ [1143 ]

Теперь ответим на ваш вопрос:

Что означает Function.prototype.__proto__?

blockquote>

Вы пытаетесь получить доступ к свойству prototype в Function функция конструктора. Помните, что prototype сам по себе является object, поэтому вы можете получить доступ к таким свойствам, как constructor и __proto__.

Function.prototype.__proto__ === Object.prototype

blockquote>

Чтобы включить сцепление, при доступе к свойству __proto__ вы ищите!

Любая функция может получить доступ ко всем свойства объекта. Как?

blockquote>

Свойство Object, скажем, toString. Вы можете сделать, A.toString() // A created at the start. Но мы никогда не создавали функцию toString для функции конструктора A!

123
задан Simon_Weaver 28 April 2009 в 19:34
поделиться

9 ответов

Как насчет класса TransferResult? (на основе ответа Станса )

/// <summary>
/// Transfers execution to the supplied url.
/// </summary>
public class TransferResult : ActionResult
{
    public string Url { get; private set; }

    public TransferResult(string url)
    {
        this.Url = url;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var httpContext = HttpContext.Current;

        // MVC 3 running on IIS 7+
        if (HttpRuntime.UsingIntegratedPipeline)
        {
            httpContext.Server.TransferRequest(this.Url, true);
        }
        else
        {
            // Pre MVC 3
            httpContext.RewritePath(this.Url, false);

            IHttpHandler httpHandler = new MvcHttpHandler();
            httpHandler.ProcessRequest(httpContext);
        }
    }
}

Обновлено: Теперь работает с MVC3 (с использованием кода из сообщения Саймона ). Он должен (не удалось его протестировать) также работать в MVC2, проверяя, работает ли он в интегрированном конвейере IIS7 +.

Для полной прозрачности; В нашей производственной среде мы никогда не используем TransferResult напрямую. Мы используем TransferToRouteResult, который, в свою очередь, вызывает TransferResult. Вот что на самом деле работает на моих производственных серверах.

public class TransferToRouteResult : ActionResult
{
    public string RouteName { get;set; }
    public RouteValueDictionary RouteValues { get; set; }

    public TransferToRouteResult(RouteValueDictionary routeValues)
        : this(null, routeValues)
    {
    }

    public TransferToRouteResult(string routeName, RouteValueDictionary routeValues)
    {
        this.RouteName = routeName ?? string.Empty;
        this.RouteValues = routeValues ?? new RouteValueDictionary();
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        var urlHelper = new UrlHelper(context.RequestContext);
        var url = urlHelper.RouteUrl(this.RouteName, this.RouteValues);

        var actualResult = new TransferResult(url);
        actualResult.ExecuteResult(context);
    }
}

И если вы используете T4MVC (если нет ... сделайте!), это расширение может пригодиться.

public static class ControllerExtensions
{
    public static TransferToRouteResult TransferToAction(this Controller controller, ActionResult result)
    {
        return new TransferToRouteResult(result.GetRouteValueDictionary());
    }
}

Используя этот маленький драгоценный камень, вы можете сделать

// in an action method
TransferToAction(MVC.Error.Index());
130
ответ дан 24 November 2019 в 01:16
поделиться

Не могли бы вы просто создать экземпляр контроллера, на который вы хотели бы перенаправить, вызвать нужный метод действия, а затем вернуть результат этого? Примерно так:

 HomeController controller = new HomeController();
 return controller.Index();
9
ответ дан 24 November 2019 в 01:16
поделиться

Просто создайте экземпляр другого контроллера и выполните его метод действия.

5
ответ дан 24 November 2019 в 01:16
поделиться

Вы можете обновить другой контроллер и вызвать метод действия, возвращающий результат. Однако это потребует от вас размещения вашего представления в общей папке.

Я не уверен, что вы имели в виду дубликат, но:

return new HomeController().Index();

Редактировать

Другой вариант может заключаться в создании вашей собственной ControllerFactory, это Таким образом, вы можете определить, какой контроллер создать.

2
ответ дан 24 November 2019 в 01:16
поделиться

Разве маршрутизация не позаботится об этом сценарии для вас? то есть для сценария, описанного выше, вы можете просто создать обработчик маршрута, который реализует эту логику.

1
ответ дан 24 November 2019 в 01:16
поделиться

Недавно я узнал, что ASP.NET MVC не поддерживает Server.Transfer (), поэтому я создал метод-заглушку (вдохновленный Default.aspx.cs).

    private void Transfer(string url)
    {
        // Create URI builder
        var uriBuilder = new UriBuilder(Request.Url.Scheme, Request.Url.Host, Request.Url.Port, Request.ApplicationPath);
        // Add destination URI
        uriBuilder.Path += url;
        // Because UriBuilder escapes URI decode before passing as an argument
        string path = Server.UrlDecode(uriBuilder.Uri.PathAndQuery);
        // Rewrite path
        HttpContext.Current.RewritePath(path, false);
        IHttpHandler httpHandler = new MvcHttpHandler();
        // Process request
        httpHandler.ProcessRequest(HttpContext.Current);
    }
12
ответ дан 24 November 2019 в 01:16
поделиться

Бесстыдное воровство форматирования Генри ...

  • быстрее и точнее проверять явное логическое значение, а не подразумеваемое; используйте вместо
  • , не используйте eval (), de () или iif () ... никогда. всегда есть способ обойти эти медленные функции
  • , которые понимают структуры, ключи, значения и способы доступа к данным запроса и структуры с использованием нотации массива. (обычно это обходится без использования функции Assessment ())
  • не используйте знаки решетки, если только вы не выводите данные или иным образом не создаете строку (не делайте этого: myFunction (arg = # myVar #))
  • прочтите и поймите разницу между ЭТОЙ и ПЕРЕМЕННОЙ областью видимости в CFC
  • , избегайте чрезмерного использования , когда вам, вероятно, потребуется использовать непосредственно перед началом вывода (до doctype, объявления xml или )
  • не бросайте вслепую значения ColdFusion в блок сценария HTML (javascript) без использования jsStringFormat ()
  • , если вы не используете < CDATA> текста в вашем XML, вы можете использовать xmlFormat () при создании XML-документа
  • не используйте реестр Windows для данных области клиента. Используйте базу данных.
  • , если ваша ИТ-архитектура позволяет, используйте данные сеанса вместо данных клиента.
  • используйте правильно и последовательно; общие данные будут утечкой в ​​вашем приложении.
  • если вы собираетесь использовать объекты Java, обратите внимание на сообщения об ошибках Java (например, «метод не найден» может не означать, что метод не существует в все, это означает, что метод не существует для аргументов, которые вы ' ve прилагается)
  • , если вам нужно читать большие файлы, либо используйте новые функции CF8 "File", либо передайте задачу Java на CF6 & 7. неэффективен для больших файлов.
  • поймите pass- по ссылке и передаче по значению, и как эти концепции работают в CF; особенно при использовании функций для изменения XML-документов
  • , как заявил Генри, всегда используйте ; также убедитесь, что вы используете правильный параметр CFSQLType для вашей СУБД (для даты, времени, метки времени и т. д.)
  • не связывайте вместе последовательность логических блоков и , используйте и < cfcase> если у вас более трех условий, вам нужно обработать
  • больше замечаний по архитектуре: Спасибо @nitin и @andy за указание на то, что исходный код не работал.

    Редактировать 4/11/2011: TempData прерывается с Server.TransferRequest, начиная с MVC 3 RTM

    Изменен приведенный ниже код, чтобы генерировать исключение, но на данный момент нет другого решения.


    Вот моя модификация, основанная на предложении Маркуса измененная версия оригинального сообщения Стэна. Я добавил дополнительный конструктор, чтобы взять словарь значений маршрута - и переименовал его в MVCTransferResult, чтобы избежать путаницы, что это может быть просто перенаправление.

    Теперь я могу сделать следующее для перенаправления:

    return new MVCTransferResult(new {controller = "home", action = "something" });
    

    Мой измененный класс:

    public class MVCTransferResult : RedirectResult
    {
        public MVCTransferResult(string url)
            : base(url)
        {
        }
    
        public MVCTransferResult(object routeValues):base(GetRouteURL(routeValues))
        {
        }
    
        private static string GetRouteURL(object routeValues)
        {
            UrlHelper url = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData()), RouteTable.Routes);
            return url.RouteUrl(routeValues);
        }
    
        public override void ExecuteResult(ControllerContext context)
        {
            var httpContext = HttpContext.Current;
    
            // ASP.NET MVC 3.0
            if (context.Controller.TempData != null && 
                context.Controller.TempData.Count() > 0)
            {
                throw new ApplicationException("TempData won't work with Server.TransferRequest!");
            }
    
            httpContext.Server.TransferRequest(Url, true); // change to false to pass query string parameters if you have already processed them
    
            // ASP.NET MVC 2.0
            //httpContext.RewritePath(Url, false);
            //IHttpHandler httpHandler = new MvcHttpHandler();
            //httpHandler.ProcessRequest(HttpContext.Current);
        }
    }
    
  • 47
    ответ дан 24 November 2019 в 01:16
    поделиться

    Я хотел перенаправить текущий запрос на другой контроллер / действие, сохраняя при этом путь выполнения точно таким же, как если бы был запрошен этот второй контроллер / действие. В моем случае Server.Request не работал, потому что я хотел добавить больше данных. Фактически это эквивалентно тому, что текущий обработчик выполняет другой HTTP GET / POST, а затем передает результаты клиенту. Я уверен, что найдутся более эффективные способы достижения этой цели, но вот что работает для меня:

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Public");
    routeData.Values.Add("action", "ErrorInternal");
    routeData.Values.Add("Exception", filterContext.Exception);
    
    var context = new HttpContextWrapper(System.Web.HttpContext.Current);
    var request = new RequestContext(context, routeData);
    
    IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(filterContext.RequestContext, "Public");
    controller.Execute(request);
    

    Ваше предположение верно: я помещаю этот код в

    public class RedirectOnErrorAttribute : ActionFilterAttribute, IExceptionFilter
    

    и использую его для отображения ошибок разработчикам, пока он в продакшене буду использовать обычный редирект. Обратите внимание, что я не хотел использовать сеанс ASP.NET, базу данных или другие способы передачи данных исключения между запросами.

    сохраняя путь выполнения точно таким же, как если бы был запрошен этот второй контроллер / действие. В моем случае Server.Request не работал, потому что я хотел добавить больше данных. Фактически это эквивалентно тому, что текущий обработчик выполняет другой HTTP GET / POST, а затем передает результаты клиенту. Я уверен, что найдутся более эффективные способы достижения этой цели, но вот что мне подходит:

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Public");
    routeData.Values.Add("action", "ErrorInternal");
    routeData.Values.Add("Exception", filterContext.Exception);
    
    var context = new HttpContextWrapper(System.Web.HttpContext.Current);
    var request = new RequestContext(context, routeData);
    
    IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(filterContext.RequestContext, "Public");
    controller.Execute(request);
    

    Ваше предположение верно: я поместил этот код в

    public class RedirectOnErrorAttribute : ActionFilterAttribute, IExceptionFilter
    

    и использую его для отображения ошибок разработчикам, пока он в продакшене буду использовать обычный редирект. Обратите внимание, что я не хотел использовать сеанс ASP.NET, базу данных или другие способы передачи данных исключения между запросами.

    сохраняя путь выполнения точно таким же, как если бы был запрошен этот второй контроллер / действие. В моем случае Server.Request не работал, потому что я хотел добавить больше данных. Фактически это эквивалентно тому, что текущий обработчик выполняет другой HTTP GET / POST, а затем передает результаты клиенту. Я уверен, что найдутся более эффективные способы достижения этой цели, но вот что мне подходит:

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Public");
    routeData.Values.Add("action", "ErrorInternal");
    routeData.Values.Add("Exception", filterContext.Exception);
    
    var context = new HttpContextWrapper(System.Web.HttpContext.Current);
    var request = new RequestContext(context, routeData);
    
    IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(filterContext.RequestContext, "Public");
    controller.Execute(request);
    

    Ваше предположение верно: я поместил этот код в

    public class RedirectOnErrorAttribute : ActionFilterAttribute, IExceptionFilter
    

    и использую его для отображения ошибок разработчикам, пока он в продакшене буду использовать обычный редирект. Обратите внимание, что я не хотел использовать сеанс ASP.NET, базу данных или другие способы передачи данных исключения между запросами.

    Фактически это эквивалентно тому, что текущий обработчик выполняет другой HTTP GET / POST, а затем передает результаты клиенту. Я уверен, что найдутся более эффективные способы достижения этой цели, но вот что работает для меня:

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Public");
    routeData.Values.Add("action", "ErrorInternal");
    routeData.Values.Add("Exception", filterContext.Exception);
    
    var context = new HttpContextWrapper(System.Web.HttpContext.Current);
    var request = new RequestContext(context, routeData);
    
    IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(filterContext.RequestContext, "Public");
    controller.Execute(request);
    

    Ваше предположение верно: я помещаю этот код в

    public class RedirectOnErrorAttribute : ActionFilterAttribute, IExceptionFilter
    

    и использую его для отображения ошибок разработчикам, пока он в продакшене буду использовать обычный редирект. Обратите внимание, что я не хотел использовать сеанс ASP.NET, базу данных или другие способы передачи данных исключения между запросами.

    Фактически это эквивалентно тому, что текущий обработчик выполняет другой HTTP GET / POST, а затем передает результаты клиенту. Я уверен, что найдутся более эффективные способы достижения этой цели, но вот что работает для меня:

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Public");
    routeData.Values.Add("action", "ErrorInternal");
    routeData.Values.Add("Exception", filterContext.Exception);
    
    var context = new HttpContextWrapper(System.Web.HttpContext.Current);
    var request = new RequestContext(context, routeData);
    
    IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(filterContext.RequestContext, "Public");
    controller.Execute(request);
    

    Ваше предположение верно: я помещаю этот код в

    public class RedirectOnErrorAttribute : ActionFilterAttribute, IExceptionFilter
    

    и использую его для отображения ошибок разработчикам, пока он в продакшене буду использовать обычный редирект. Обратите внимание, что я не хотел использовать сеанс ASP.NET, базу данных или другие способы передачи данных исключения между запросами.

    в продакшене буду использовать обычное перенаправление. Обратите внимание, что я не хотел использовать сеанс ASP.NET, базу данных или другие способы передачи данных исключения между запросами.

    в продакшене буду использовать обычное перенаправление. Обратите внимание, что я не хотел использовать сеанс ASP.NET, базу данных или другие способы передачи данных исключения между запросами.

    7
    ответ дан 24 November 2019 в 01:16
    поделиться

    Не ответ сам по себе, но очевидно, что требование заключается не только в том, чтобы фактическая навигация "делала" эквивалентную функциональность Webforms Server.Transfer(), но и в том, чтобы все это было полностью поддержано в рамках юнит-тестирования. Поэтому ServerTransferResult должен "выглядеть" как RedirectToRouteResult и быть как можно более похожим на иерархию классов.

    Я думаю сделать это, посмотрев на рефлектор и сделав все, что делает класс RedirectToRouteResult, а также различные методы базового класса контроллера, а затем "добавив" последний в контроллер с помощью методов расширения. Может быть, это могут быть статические методы внутри одного класса, для простоты/безмятежности загрузки?

    Если я обойду это, то выложу, иначе, может быть, кто-то другой меня опередит!

    .
    0
    ответ дан 24 November 2019 в 01:16
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: