Reputation: 5157
I have the following class, where a user will access a controller AT/1/2
which means project 1, step 2. If the user enters a project and not a step (2nd method/route) it should use step 99. If the user fails to enter anything, it should use project 1, step 99. I can easily fix this by calling the overloaded method manually, but I thought I should be able to accomplish the same thing with RedirectToAction. However in the 2nd and 3rd methods, v is null in my unit tests.
My RegisterRoutes looks like:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes(); //MVC 5 Attribute Routes
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
I'm not sure what I'm missing here.
public class ATController : Controller
{
[AllowAnonymous]
[Route("{project}/{step}")]
public ActionResult Index(int project, int step)
{
var m = new ATViewModel();
m.Project = project;
m.Step = step;
return View(m);
}
[AllowAnonymous]
[Route("{project}")]
public ActionResult Index(int project)
{
var v = RedirectToAction("Index", new { project, step = 99 });
return v;
}
[AllowAnonymous]
public ActionResult Index()
{
var v = RedirectToAction("Index", new { project = 1, step = 99 });
return v;
}
}
Upvotes: 2
Views: 528
Reputation: 247098
Referencing Attribute Routing in ASP.NET MVC 5, there were some minor updates needed on your controller
[RoutePrefix("at")]
public class ATController : Controller
{
//GET /at/1/2
[AllowAnonymous]
[Route("{project}/{step}")]
public ActionResult Index(int project, int step)
{
var m = new ATViewModel();
m.Project = project;
m.Step = step;
return View(m);
}
//GET /at/1
[AllowAnonymous]
[Route("{project}")]
public ActionResult Index(int project)
{
var v = RedirectToAction("Index", new { project = project, step = 99 });
return v;
}
//GET /at
[AllowAnonymous]
[Route("")]
public ActionResult Index()
{
var v = RedirectToAction("Index", new { project = 1, step = 99 });
return v;
}
}
Here are also some unit tests for your controller that all pass (GREEN) when tested.
[TestClass]
public class MvcControllerAttributeRouteTests : ControllerUnitTests {
[TestMethod]
public void Index_Should_Return_ViewResult_With_Model() {
//Arrange
int project = 1;
int step = 2;
var controller = new ATController();
//Act
var actionResult = controller.Index(project, step);
var viewResult = actionResult as ViewResult;
//Assert
Assert.IsNotNull(viewResult);
Assert.IsNotNull(viewResult.Model);
Assert.IsInstanceOfType(viewResult.Model, typeof(ATViewModel));
var viewModel = viewResult.Model as ATViewModel;
Assert.AreEqual(project, viewModel.Project);
Assert.AreEqual(step, viewModel.Step);
}
[TestMethod]
public void Project_Supplied_No_Step_Should_Redirect_To_Index() {
//Arrange
int project = 1;
var controller = new ATController();
//Act
var actionResult = controller.Index(project);
var result = actionResult as RedirectToRouteResult;
//Assert
Assert.IsNotNull(result);
Assert.AreEqual("Index", result.RouteValues["action"], "the redirection was to at.index action");
Assert.AreEqual(project, result.RouteValues["project"]);
}
[TestMethod]
public void No_Porject_No_Step_Should_Redirect_To_Index() {
//Arrange
var controller = new ATController();
//Act
var actionResult = controller.Index();
var result = actionResult as RedirectToRouteResult;
//Assert
Assert.IsNotNull(result);
Assert.AreEqual("Index", result.RouteValues["action"], "the redirection was to at.index action");
CollectionAssert.Contains(result.RouteValues.Keys, "project");
CollectionAssert.Contains(result.RouteValues.Keys, "step");
}
}
Upvotes: 1