Post и get запросы в ASP.NET MVC

110
08 июня 2019, 01:20

Доброе утро. Есть вопрос связанный с отправкой get и post запросов. Разбираю примерчики с метанита и немного не понятно. Вот пример кода get запроса:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Книжный магазин</title>
</head>
<body>
    <div>
        <h3>Распродажа книг</h3>
        <table>
            <tr>
                <td><p>Название книги</p></td>
                <td><p>Автор</p></td>
                <td><p>Цена</p></td>
                <td></td>
            </tr>
            @foreach (var b in ViewBag.Books)
            {
                <tr>
                    <td><p>@b.Name</p></td>
                    <td><p>@b.Author</p></td>
                    <td><p>@b.Price</p></td>
                    <td><p><a href="/Home/Buy/@b.Id">Купить</a></p></td>
                </tr>
            }
        </table>
    </div>
</body>
</html>

И action в контроллере обрабатывающий этот запрос:

[HttpGet]
public ActionResult Buy(int id)
{
    ViewBag.BookId = id;
    return View();
}

И post запрос с его обработчиком:

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Покупка</title>
</head>
<body>
    <div>
        <h3>Форма оформления покупки</h3>
        <form method="post" action="">
            <input type="hidden" value="@ViewBag.BookId" name="BookId" />
            <table>
                <tr>
                    <td><p>Введите свое имя </p></td>
                    <td><input type="text" name="Person" /> </td>
                </tr>
                <tr>
                    <td><p>Введите адрес :</p></td>
                    <td>
                        <input type="text" name="Address" />
                    </td>
                </tr>
                <tr><td><input type="submit" value="Отправить" /> </td><td></td></tr>
            </table>
        </form>
    </div>
</body>
</html>
[HttpPost]
        public string Buy(Purchase purchase)
        {
            purchase.Date = DateTime.Now;
            db.Purchases.Add(purchase);
            db.SaveChanges();
            return "Спасибо," + purchase.Person + ", за покупку!";
        }

В связи с этим у меня есть несколько вопросов.

1) Как мне сделать так что бы отправить get запрос другим способом, таким как в этом примере отправляется post? То есть сменить там тип запроса на гет в form и сделать то же самое но этим способом, либо с помощью эквивалентного этому коду html-хелпера beginform.

2)Если например будет 2 метода либо get либо post относящихся к одной вьюхи и называющихся одинаково как я смогу выбрать к какому я обращаюсь.

3)Почему в это примере именно таким образом разделены запросы? Можно же например то что тут отправляется get запросом сделать наоборот post, а то что тут отправляется post-ом, отправить get-ом.

4)В этом примере в методе Buy(Purchase purchase) метод принимает модель:

public class Purchase
    {
        public int PurchaseId { get; set; }
        public string Person { get; set; }
        public string Address { get; set; }
        public DateTime Date { get; set; }
        public virtual ICollection<Book> Books { get; set; }
        public Purchase()
        {
            Books = new List<Book>();
        }
    }

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

Код view:

<table>
            <tr>
                <td><p>Название книги</p></td>
                <td><p>Автор</p></td>
                <td><p>Цена</p></td>
                <td></td>
            </tr>
            @foreach (var b in ViewBag.Books)
            {
                <tr>
                    <td><p>@b.Name</p></td>
                    <td><p>@b.Author</p></td>
                    <td><p>@b.Price</p></td>
                    <td>
                        <form method="post" action="/Home/Buy">
                            <input type="hidden" value="@b.Id" name="Id" />
                            <table>
                                <tr><td><input type="submit" value="Отправить" /> </td></tr>
                            </table>
                        </form>
                    </td>
                </tr>
            }
        </table>

Код контроллера:

public class HomeController : Controller
    {
        Context db = new Context();
        public ActionResult Index()
        {
            IEnumerable<Book> books = db.Books;
            ViewBag.Books = books;
            return View();
        }
        [HttpPost]
        public ActionResult Buy(int id)
        {
            ViewBag.BookId = id;
            return View();
        }
        [HttpPost]
        public string Buy(Purchase purchase)
        {
            purchase.Date = DateTime.Now;
            db.Purchases.Add(purchase);
            db.SaveChanges();
            return "Спасибо," + purchase.Person + ", за покупку!";
        }
    }

Как указать к какому контретно методу обращаться?

Answer 1
  1. @Html.BeginForm("actionName", "ControllerName", FormMethod.Get).
  2. Uri запроса будет сопоставлятся с маршрутами из RouteTable и типом запроса.
  3. Потому-что запросы типа POST не являются идемпотентеными. http://www.restapitutorial.ru/lessons/idempotency.html
  4. Необходимо реализовать "кастомный" привязчик(ModelBinder) реализуя интерфейс IModelBinder. https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.imodelbinder?view=aspnet-mvc-5.2
Answer 2

1)Обычно GET-запросы, это те запросы которые возвращают View, а POST-запросы отправляют какие-либо данные с вашей View. Если на форме стоит атрибут method="post", то в контроллере будет искаться именно метод c [HttpPost], отсутствие method="post" говорит о том, что это get-запрос.

2) Для этого вы указываете к какому именно методу контроллера вы обращаетесь через action="название метода".

3) Потому что, первый метод возвращает View "Buy",

[HttpGet]
public ActionResult Buy(int id)
{
    ViewBag.BookId = id;
    return View();
}

а второй метод получает данные с этой View, обрабатывает их (добавляет данные в БД) и что-то возвращает.

[HttpPost]
public string Buy(Purchase purchase)
{
    purchase.Date = DateTime.Now;
    db.Purchases.Add(purchase);
    db.SaveChanges();
    return "Спасибо," + purchase.Person + ", за покупку!";
}
READ ALSO
Как сделать изображение блоком?

Как сделать изображение блоком?

Как сделать данную картинку блоком и поместить внутри нее текст? Затем, чтобы изображение меняло размер в зависимости от разрешения монитора?

130
Подскажите по фрагменту кода

Подскажите по фрагменту кода

Немного не понятно,что происходит во втором циклеПочему из переменной len вычитаем индекс и единицу

94
Форматированный консольный вывод С#

Форматированный консольный вывод С#

Имеется n строк и n чиселНужно вывести их так, чтобы числа начинались с одинаковой позиции в строке:

148