Folks, I'm looking for a solution to avoid duplication when I make the same method Post for a several controllers
Can you tell me a solution how to make a method with sending a form that I can use in any controller and return a model with an error?
I have several Controllers in which I will have a form sending (in the real project it is a service with email sending). On showed it in the screenshots and code.
public class HomeController : BaseController
{
public IActionResult Index()
{
return View();
}
}
public class AdditionalController : BaseController
{
public IActionResult Index()
{
return View();
}
}
public class BaseController : Controller
{
[HttpPost]
public IActionResult ScheduleDemo(UserModel model)
{
if (ModelState.IsValid)
{
return Content("The Best");
}
return PartialView(@"~/Views/Shared/Partial/ScheduleDemo.cshtml", model);
}
}
ASPX
HomeController Index.cshtml
<h1>Home</h1>
@await Html.PartialAsync("Partial/ScheduleDemo")
ASPX
AdditionalController Index.cshtml
<h1>Additional</h1>
@await Html.PartialAsync("Partial/ScheduleDemo")
I did not create a view for the BaseController in ScheduleDemo, but use a partial view
ASPX
ScheduleDemo.cshtml
@model UserModel
<form asp-controller="Base" asp-action="ScheduleDemo" method="post" asp-antiforgery="true">
<p>
<label asp-for="@Model.UserName">UserName</label><br />
<input type="text" asp-for="@Model.UserName" />
<span asp-validation-for="UserName" style="color: red;"></span>
</p>
<p>
<label asp-for="@Model.Age">Age</label><br />
<input asp-for="@Model.Age" />
<span asp-validation-for="Age" style="color: red;"></span>
</p>
<p>
<label asp-for="@Model.City">City</label><br />
<input type="text" asp-for="@Model.City" />
</p>
<input type="submit" value="Send" />
</form>
In order to avoid code duplication, I tried to make BaseController and define this form sending in it, but when I make a post I go to another route localhost://Base/... and I need to stay at the same url, for example localhost://Aditional/... The biggest problem is not in that url, when I send a form successfully, everything is OK, the problem is when ModelState.IsValid == false... then model returns to me, but the page says that View by this url does not exist or in my case redirect to PartialView and it is logical, because I send form from parent controller...
CodePudding user response:
There are a few ways to avoid code duplication when making the same method POST for several controllers. One way would be to create a base controller that all your other controllers inherit from. In the base controller, you can define the POST method and have it return a model with an error. Your other controllers can then override this method if they need to.
Another way to avoid code duplication is to use a service layer. In the service layer, you can define the POST method and have it return a model with an error. Your controllers can then call the service layer method to avoid duplicating code.
For example, let's say you have a controller that needs to make a POST request to a URL. You can define a method in the base controller like this:
public class BaseController : Controller {
[HttpPost]
public IActionResult PostToUrl(string url, UserModel model) {
if (ModelState.IsValid) {
return Content("The Best");
}
return PartialView(@"~/Views/Shared/Partial/PostToUrl.cshtml", model);
}
}
Your other controllers can then inherit from the BaseController and call the PostToUrl method.
If you need to make the same POST request from multiple controllers, you can also create a service layer. In the service layer, you can define the POST method and have it return a model with an error. Your controllers can then call the service layer method to avoid duplicating code.
For example, let's say you have a controller that needs to make a POST request to a URL. You can define a method in the service layer like this:
public class MyService {
public IActionResult PostToUrl(string url, UserModel model) {
if (ModelState.IsValid) {
return Content("The Best");
}
return PartialView(@"~/Views/Shared/Partial/PostToUrl.cshtml", model);
}
}
Your controllers can then call the MyService.PostToUrl method to avoid duplicating code.