There are lots of questions asking about this logic in reverse, however, I can't find an answer for my issue. I'm new to MVC so might not have the terminology specified correctly.
I have a View containing a form, where a user can request a product. The same View is used regardless of the product, but specific fields are shown in the form relating to that particular product, e.g.
public class RequestController : Controller
{
// This bit works fine and displays the appropriate form in the view
public ActionResult MyProduct(string id)
{
if (string.IsNullOrWhiteSpace(id))
{
return new HttpNotFoundResult();
}
ProductRequest qd = new ProductRequest();
switch (id)
{
case "Beer":
qd.RequestType = Models.RequestType.Beer;
break;
case "Coffee":
qd.RequestType = Models.RequestType.Coffee;
break;
case "Soda":
qd.RequestType = Models.RequestType.Soda;
break;
}
return View("Index", qd);
}
// Need to get all forms rendered by the above to post here...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MyProduct(ProductRequest qd)
{
if (!ModelState.IsValid)
{
return View(qd);
}
else
{
// To do ...
}
}
}
When the form is rendered in the view, using...
@using (Html.BeginForm())
...the rendered HTML shows a different form target URL for each product type, e.g:
<form action="/Request/MyProduct/Beer" method="post">
Can I make the form action
property use the same controller/method regardless of the product type? e.g.
<form action="/Request/MyProduct" method="post">
I assume there are different ways to achieve this given the flexibility MVC seems to offer, but I'm looking for best practice please as a learning experience.
What added value gives you the Html.BeginForm
helper over writting the html yourself, apart from preventing you to easily control your action url?
Thankfully, HTML helpers are no more the way to go with .Net Core. Use Tag helpers instead, which are a lot more usable and will not hinder you doing what you need in most cases. From their documentation:
The markup is much cleaner and easier to read, edit, and maintain than the HTML Helpers approach. The C# code is reduced to the minimum that the server needs to know about.
Personally, I have banned most Html helpers usages, there are just getting in my way instead of helping me.
If tag helpers are not available with your target framework, write your html code yourself, that is frequently even more concise than using html helpers (as illustrated in this answer).
<form action"@Url.Action("MyProduct", "Request")" method="post">
@* Add [ValidateAntiForgeryToken, HttpPost] attributes to target action *@
@Html.AntiForgeryToken()
...
</form>
(And even better, use UrlHeper extensions to define and centralize your URIs, instead of calling Url.Action
inside your views or controllers.)
For completeness, I should mention that most input fields html helper extensions (those suffixed with For
) have the added value of exploiting data-annotations of your view-models. But I consider those annotations as bad practice, because they handle subjects which are not the view-model responsibility in strict MVC pattern. (Display labels? Should be controlled by the view. Validation rules? Should be controlled by the controller. Action argument and/or parameter model? No reason to be bound to the view-model names.)