Pomster
Pomster

Reputation: 15197

Overloading with MVC Controllers

I have an action with the same name, one expecting no parameters and the other expecting an ID, when i try navigate through my url i get the following exception.

An unhandled exception occurred while processing the request.

AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:

Mailer.Controllers.MailBuilderController.MailBody (Mailer) Mailer.Controllers.MailBuilderController.MailBody (Mailer)

My MailBuilder controller.

//[HttpGet("mailbuilder/MailBody")]
public IActionResult MailBody()
{
   Body model = new Body();
   return View(model);
}

//[HttpGet("mailbuilder/MailBody/{id}")]
public IActionResult MailBody(int id)
{
   Body model = _mailBuilderService.GetBody(id);
   return View(model);
}

If i remove the comments above i am able to navigate but i am not able to redirect to action in the below method.

public IActionResult SaveBody(Body model)
{
  _mailBuilderService.AddBody(model);
  return RedirectToAction("MailBody", model.Id);
}

Upvotes: 3

Views: 474

Answers (2)

Dillon
Dillon

Reputation: 707

What about making the int nullable?

public IActionResult MailBody(int? id)
{
   Body model = id.HasValue ? _mailBuilderService.GetBody(id.Value) : new Body();
   return View(model);
}

To clarify, if you're using default routing then the id is likely set to id = RouteParameter.Optional so in essence the two ActionResults are the same.

Upvotes: 1

Michael Coxon
Michael Coxon

Reputation: 5510

If it is anything like the previous versions of MVC then you will need to uncomment those route attributes ([HttpGet("mailbuilder/MailBody/{id}")]) but also rename your post action to the same name. Alternatively, you can set the action in the form helper (if that still exists).

Also so the router can find the right method you need to provide the route data as an object return RedirectToAction("MailBody", new { id = model.Id });

The following code example is untested but I think it will be on the right track...

[HttpGet("mailbuilder/MailBody")]
public IActionResult MailBody()
{
   Body model = new Body();
   return View(model);
}

[HttpGet("mailbuilder/MailBody/{id}")]
public IActionResult MailBody(int id)
{
   Body model = _mailBuilderService.GetBody(id);
   return View(model);
}

[HttpPost("mailbuilder/MailBody")]
public IActionResult MailBody(Body model)
{
  _mailBuilderService.AddBody(model);
  return RedirectToAction("MailBody", new { id = model.Id });
}

Upvotes: 2

Related Questions