Обработка почтовых запросов в ASP.NET MVC - PullRequest
4 голосов
/ 23 февраля 2010

Недавно я начал работать с MVC, до этого я использовал «классический» ASP.NET.

После использования Ruby on Rails (RoR) мне интересно, как реализовать обработку запросов POST в MVC, аналогично тому, как работает RoR. В RoR вы используете метод Post, поэтому вам нужна только одна функция для представления.

В ASP.NET MVC мне нужно использовать 2 отдельные функции для GET и для POST, поэтому мне нужно дважды инициализировать одни и те же данные, и я не люблю повторять что-то в моем коде. *

Как я могу проверить, является ли запрос POST одним методом?

Обновление:

Решение найдено: я должен использовать Request.HttpMethod.

Спасибо!

Ответы [ 5 ]

9 голосов
/ 24 марта 2010

Я столкнулся с этим вопросом, желая узнать то же самое. Ниже приводится подробное описание моей ситуации и решения, которое я использовал (который использует другие ответы, представленные здесь). Первоначально я пытался использовать метод двух отдельных методов, но столкнулся с проблемой, когда сигнатуры методов этих методов стали идентичными.

У меня есть страница, на которой отображаются данные отчета. В верхней части страницы находится форма с некоторыми полями, которые позволяют пользователю указать параметры отчета, такие как дата начала, дата окончания и т. Д.

Первоначально я подошел к этому, создав два отдельных метода для обработки методов Get и Post. Метод post перенаправляет браузер на метод get, чтобы любые заданные параметры были добавлены в строку запроса и браузер не запрашивал у пользователя диалоговое окно с сообщением о том, что он собирается повторно отправить введенные данные. если они освежатся. Примечание. Позже я понял, что мог бы добиться этого, установив для атрибута метода моего элемента формы значение «Получить», но я думаю, что в идеале контроллер не должен знать, как реализовано представление, поэтому, на мой взгляд, это не имеет значения.

Когда я разработал эти два метода, я в конечном итоге оказался в ситуации, когда сигнатуры методов стали идентичными. Более того, мой код для этих двух методов стал почти идентичным, поэтому я решил объединить их в один метод и просто проверить глагол запроса, чтобы я мог сделать что-то немного отличающееся, когда запрос не является «Get». Дистиллированный пример моих двух методов показан ниже:

    // this will not compile because the method signatures are the same

    public ActionResult MyReport(DateRangeReportItem report)
    {
        // if there are no validation errors and the required report parameters are completed
        if (ModelState.IsValid && report.ParametersAreComplete)
        {
            // retrieve report data and populate it on the report model
            report.Result = GetReportData(report.CreateReportParameters());
        }

        return View(report);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult MyReport(DateRangeReportItem report)
    {
        if (ModelState.IsValid && report.ParametersAreComplete)
        {
            // redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
            // this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
            return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
        }
        else
        {
            // there were validation errors, or the report parameters are not yet complete
            return View(report);
        }
    }

Почему я принимаю объект модели в качестве параметра для моего метода get? Причина в том, что я хотел воспользоваться логикой проверки, уже встроенной в объект модели. Если кто-то переходит на мою страницу напрямую со всеми параметрами, уже указанными в строке запроса, я хочу продолжить, получить данные отчета и отобразить их на странице. Однако, если параметры, указанные в строке запроса, являются недопустимыми, я также хочу, чтобы ошибки проверки появлялись на странице. Поместив объект моей модели в качестве параметра, инфраструктура MVC автоматически попытается заполнить его и будет фиксировать любые ошибки валидации без какой-либо дополнительной работы с моей стороны.

Я использовал другие ответы на этот вопрос, чтобы создать свойство RequestHttpVerb для базового класса контроллера в моем проекте:

    public HttpVerbs RequestHttpVerb
    {
        get { return (HttpVerbs)Enum.Parse(typeof(HttpVerbs), this.Request.HttpMethod, true); }
    }

Итак, мой консолидированный метод выглядит следующим образом:

    [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
    public ActionResult MyReport(DateRangeReportItem report)
    {
        // check if there are any validation errors in the model
        // and whether all required report parameters have been completed
        if (ModelState.IsValid && report.ParametersAreComplete)
        {
            // this is unnecessary if the form method is set to "Get"
            // but within the controller I do not know for sure if that will be the case in the view
            if (HttpVerbs.Get != this.RequestHttpVerb)
            {
                // redirect to the same action so that if the user refreshes the browser it will submit a get request instead of a post request
                // this avoids the browser prompting the user with a dialog saying that their data will be resubmitted
                return RedirectToAction("MyReport", new { StartDate = report.StartDate, EndDate = report.EndDate });
            }

            // there were no validation errors and all required report parameters are complete
            // retrieve report data and populate that data on the model
            report.Result = GetReportData(report.CreateReportParameters());
        }

        // display the view with the report object
        // Any model state errors that occurred while populating the model will result in validation errors being displayed
        return View(report);
    }

Это мое текущее решение проблемы. Я бы предпочел не проверять свойство Request.HttpMethod, чтобы определить, нужно ли мне выполнять перенаправление, но я не нашел другого решения моей проблемы. Я был бы в порядке с сохранением двух отдельных методов для обработки запросов Get и Post, но идентичная сигнатура метода предотвратила это. Я бы предпочел переименовать мой метод-обработчик действия Post, чтобы избежать конфликта сигнатур метода и использовать какой-либо механизм, чтобы указать инфраструктуре MVC, что мой переименованный метод должен по-прежнему обрабатывать действие «MyReport», но я не знаю ни одного такого механизма в рамках MVC.

5 голосов
/ 24 февраля 2010

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

Если вам нужно узнать, был ли это GET или POST, вы можете проверить с помощью Request.HttpMethod в своем действии, но я бы посоветовал использовать отдельный метод, украшенный атрибутом [AcceptVerbs (HttpVerbs.Post)], как предложено другие постеры.

3 голосов
/ 23 февраля 2010

Вы не регистрируетесь в ASP.NET MVC. Вы украшаете свой метод атрибутом [AcceptVerbs(HttpVerbs.Post)], чтобы указать, что метод применяется только к публикации, и принимаете модель в методе, используемом для обработки сообщения.

Я бы настоятельно рекомендовал сделать пошаговое руководство по NerdDinner , чтобы лучше понять каркас ASP.NET MVC.

1 голос
/ 23 февраля 2010

Вы можете взглянуть на свойство Request.HttpMethod .

0 голосов
/ 23 февраля 2010

Правильный способ сделать это - использовать ModelBinding во время запроса Post.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(EmployeeViewModel model)
{
 //validate data, save employee, handle validation errors...
}

Таким образом, вам не нужно будет заново инициализировать ваши данные.

...