let me start with explaining what I am trying to do. I have a form with a drop down where on the change of the value triggers a label text to change. To do this I attached a onchange script event to fire off.
<select onchange="ChangeLabel()" id="ContainerValue" asp-for="Container" class="form-control"/>
The Label
<label id="AddressLabel" asp-for="Container" class="control-label"/>
The script it calls is
<script>
function ChangeLabel() {
var val = $('#ContainerValue').val();
$.ajax({
url: '/Rundown/GetLabel/' + val ,
type: "GET",
dataType: "text",
success: function (labelText) {
$("#AddressLabel").html(labelText);
}
});
}
</script>
So I create a action in my controller called GetLabel with a parameter id.
[HttpGet]
// GET: Rundown/GetLabel/5
public string GetLabel(int id)
{
return "x";
}
So I am pretty sure I am using default routing that's created on setup of project. As far as I know I didn't mess with this.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Now when I change the selection in the drop down the change request gets fired of and a request is made to /Rundown/GetLabel/1
but it returns a 404 error. Just for testing purposes I noticed that if I did /Rundown/GetLabel/?id=1
I would hit my GetLabel action and would get back my "x"
string value. Any idea why I am not seeing my action get hit with the normal
[controller]/[action]/[id]
routing I would of expected to work?
The only other related information I can think of is a route in a fixture above the controller class.
[Route("[controller]/[action]")]
public class RundownController : Controller
You are mixing attribute and convention-based routes which is causing a conflict.
The attribute route will take priority here over the convention-based route and since you do not have a route template for the action parameter it is not being found.
Add a route template for the action
Route("[controller]/[action]")]
public class RundownController : Controller {
// GET: Rundown/GetLabel/5
[HttpGet("{id}")]
public string GetLabel(int id) {
return "x";
}
}
Having the attribute route on the controller and just the HttpGet
on the action meant that the URL would have looked like
Rundown/GetLabel?id=5
By including the route template parameter [HttpGet("{id}")]
you get the desired behavior.
An alternative is to remove the Route("[controller]/[action]")]
from the top of the controller and allow the default routing definition from the startup MapRoute