Контроллер:
public async Task<IActionResult> Cart()
{
//some logic
}
public async Task<IActionResult> Payment()
{
//some logic
}
Корзина.cshtml:
<form method = "post" asp-action = "Payment" asp-controller = "Tech">
<button></button>
</form>
Я хочу, чтобы пользователи не могли просто набрать MyDomain/MyController/Payment и получить доступ к странице оплаты. Я хочу убедиться, что пользователь нажал кнопку на странице корзины, чтобы ему было разрешено перейти на страницу оплаты. Решение, о котором я подумал, — использовать TempData[], чтобы сохранить имя последней посещенной страницы, а затем проверить, имеет ли словарь значение null или есть ли в нем имя, но я уверен, что должен быть лучший способ.
@СебастьянС. У меня есть внутренний код, который проверяет, есть ли в корзине запись, я просто не включил ее, чтобы вопрос был проще понять, потому что я прошу что-то еще. Также каждая корзина сохраняется в базе данных. Но спасибо за ваше беспокойство.





Как я могу гарантировать, что методы контроллера вводятся только в конкретная последовательность
Что ж, согласно вашему сценарию и описанию, с этим можно справиться несколькими способами, кроме TempData[]. Также здесь tempData не является идеальным или лучшим способом сделать это, поскольку tempdata не является постоянным.
Идеальными способами можно рассмотреть либо привязку модели, либо использование состояния сеанса. Используя оба способа, сначала мы проверим статус последней посещенной пользователем страницы, и если пользователи перейдут со страницы корзины, мы разрешим им посетить страницу оплаты. В противном случае их можно снова перенаправить на страницу корзины.
Давайте посмотрим на практике, как мы можем этого добиться,
Использование привязки модели:
Это один из простых способов реализовать ваше требование. Мы бы установили статус страницы при загрузке страницы корзины как скрытое значение и проверяли бы значение при загрузке страницы оплаты, если оно истинно или нет, означает, что пользователи посещают страницу напрямую или из корзины.
Давайте реализуем это:
Демо-модель:
public class TransitionModel
{
public bool FromCart { get; set; }
}
Контроллер:
public class TechController : Controller
{
public IActionResult Cart()
{
var model = new TransitionModel();
return View(model);
}
//[HttpPost]
public async Task<IActionResult> Payment(TransitionModel model)
{
if (model.FromCart)
{
return View();
}
else
{
return RedirectToAction("Cart");
}
}
}
Вид:
@model TransitionModel
<form method = "get" asp-action = "Payment" asp-controller = "Tech">
<input type = "hidden" asp-for = "FromCart" value = "true" />
<button type = "submit">Go to Payment</button>
</form>
Примечание. Для загрузки страницы оплаты у вас, вероятно, есть одна страница для загрузки представления, которая является типом GET, а другое действие должно иметь метод с POST, который будет получать запрос на платеж. В обоих действиях вы можете фильтровать значение FromCart. Я проверяю только загрузку, поэтому использовал GET. Вы можете попробовать оба.
Выход:
Промежуточное программное обеспечение с сеансовым подходом:
Чтобы использовать промежуточное программное обеспечение и подход состояния сеанса, прежде всего нам нужна переменная сеанса, в которой мы будем хранить информацию о последней посещенной странице. В этом случае, если последней посещенной страницей является корзина, мы бы разрешили пользователю посещать оплату чего-либо, кроме этого, которое мы бы проигнорировали.
Проверим реализацию:
public class NavigationMiddleware
{
private readonly RequestDelegate _next;
public NavigationMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var path = context.Request.Path.Value.ToLower();
if (!path.Contains("/payment") && !path.Contains("/cart"))
{
await _next(context);
return;
}
context.Session.SetString("LastVisitedPage", path);
await _next(context);
}
}
Программа.cs:
app.UseSession();
app.UseMiddleware<NavigationMiddleware>();
Примечание. Как видите, мы сохраняем текущую страницу в сеансе и игнорируем пути, которые не являются частью последовательности. Вы можете обратиться к этому официальному документу для получения сведений о промежуточном программном обеспечении и управлении состоянием сеанса.
Я вижу, как работают оба способа. Спасибо, что поделились ими. Я просто ожидал, что Microsoft придумала что-то более простое, например, атрибут метода, который проверяет, поступил ли запрос с определенной страницы. Для Asp.Net имело бы смысл иметь эту функцию.
На данный момент в asp.net нет встроенного метода, атрибута, чтобы вы могли напрямую использовать его, и у нас есть эти варианты для удовлетворения ваших требований.
Прежде всего, вам следует добавить проверку во внешнем интерфейсе, если при отправке запроса на оплату есть какая-либо запись в корзине, в противном случае заблокируйте запрос. Всегда имейте в виду, что этой проверкой можно довольно легко манипулировать во внешнем интерфейсе, поэтому в целях безопасности вам потребуется еще одна проверка в серверной части. Веб-сервисы RESTful не имеют состояния. Поэтому вам необходимо передать корзину на маршрут оплаты или сохранить корзину в базе данных и загрузить ее на маршрут оплаты.