I have recently started to use Areas in my .net core web app to organise hundreds of files in the project. It all worked well, until now.
I have a controller in its own area, with these decorators
namespace MyApp.Controllers
{
[Area("Doc")]
[Route("doc")]
public class DailyOperatingCtrlController : Controller
{
...
}
}
Then each action method is decorated like so:
[Authorize]
[Route("[action]/{page:int?}")]
public async Task<IActionResult> DOC()
{
...
}
I used this post as an example: How to use an Area in ASP.NET Core
My Startup.cs routes look like this:
app.UseMvc(routes =>
{
routes.MapRoute("areaRoute", "{area:exists}/{controller=Admin}/{action=Index}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
In the same controller I have several methods that all have [HttpPost] decorator and work as expected.
Here is the specific issue I am having:
I have this method, loads a page with a form:
[Authorize]
[Route("[action]/{page:int?}")]
public async Task<IActionResult> DocService()
{
var model = new ForecastViewModel
{
{ ... }
};
return View(model);
}
Then this method is for POST:
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
[Route("[action]/{page:int?}")]
public async Task<IActionResult> DocService(int ForecastRtnId, string checkgroup, [Bind("{...}")] ForecastRtn forecastRtn)
{
/* Save data to a table and redirect back to the GET method */
{ ... }
}
Now so far so good, this works fine. The problem I have is with a child window I open from within the above page. So within the DocService.cshtml file I have a short js script that opens up a popup:
function PopupService() {
url = "@Url.Action("DocServiceComment", "DailyOperatingCtrl", new { Area = "Doc", Id = "ID" })".replace("ID",parseInt(@lab_id));
title = "Some Title";
w = 600;
h = 400;
{ ... }
}
I am using Url.Action, I am also passing Area name and Id parameter. The popup is a single input box form that saves an user comment to separate audit table. Nothing fancy.
[Authorize]
[Route("[action]/{page:int?}")]
public async Task<IActionResult> DocServiceComment(int? Id)
{
if (Id == null)
{
return NotFound();
}
var forecast = await _context.Forecast.SingleOrDefaultAsync(m => m.ForecastId == Id);
if (forecast == null)
{
return NotFound();
}
return View(forecast);
}
So far so good, the popup loads correctly and has the correct comment in the input box (if there was one left already)
What I have noticed - and I believe this is where the issue is - that the URL of the popup looks like this:
http://localhost:5000/doc/DocServiceComment?Id=2
Instead of this:
http://localhost:5000/doc/DocServiceComment/2
But I might be wrong here and confusing matters. When I try to submit this popup I get 404 error.
My post method for DocServiceComment:
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
[Route("[action]/{page:int?}")]
public async Task<IActionResult> DocServiceComment(int id, [Bind("{ ...}")] Forecast forecast)
{
/* Save stuff and redirect back to get */
}
Which obviously does not get called at all.
Inside my DocServiceComment.cshtml I've tried this:
<form asp-area="Doc" asp-controller="DailyOperatingCtrl" asp-action="DocServiceComment">
/* Form stuff goes here */
</form>
I've tried to find any info on this but to no avail, which makes me think I am making a rookie error somewhere?
Also another hint, if we take this URL
http://localhost:5000/doc/DocServiceComment?Id=2
and remove the ?Id=2 it also gives 404 error.
This is the only page that behaves like that, and I need help figuring out what is going on.