Clarification of ASP.NET MVC routing and model binding - asp.net-mvc

In ASP.NET MVC, I have recently found out that:
This doesn't work and results in an HTTP 404.
public class TestController : Controller
{
[HttpGet]
[HttpPost]
public ActionResult Index(TestModel model)
{
return View(model);
}
}
This works fine.
public class TestController : Controller
{
public ActionResult Index(TestModel model)
{
return View(model);
}
}
This also works fine:
public class TestController : Controller
{
[HttpGet]
[ActionName("Index")]
public ActionResult GetIndex(TestModel model)
{
return View("Index", model);
}
[HttpPost]
[ActionName("Index")]
public ActionResult PostIndex(TestModel model)
{
return View("Index", model);
}
}
I would like an explanation of why the first version doesn't work, but the other two do work. I would also appreciate if someone could tell me how I can modify the first version to make it work. I like the first version because it is more concise (1 method rather than 2) and also filters out unnecessary HTTP methods.

HTTP verb attributes are mutually exclusive, a request cannot be both GET and POST at the same time. Instead, you have to do this:
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult Index(TestModel model) { ... }

Related

How to declare controller action method return type?

I understand ActionResult is the base class for RedirectResult class so essentially functionality for the code below is the same.
Is there an advantage to explicitly specify the appropriate result class as a return type as opposed to the base class?
public ActionResult Index()
{
return Redirect("Home/Contact");
}
public RedirectResult Index()
{
return Redirect("Home/Contact");
}
if you need redirect quickly to another action without lost any data and this action is in the same controller , call the action as a method:
public IActionResult Index()
{
return Contact();
}
public IActionResult Contact()
{
....
}
which one from another redirections methods is better is an opinion-based question and is not allowed by SO policy

Add 2 ActionResult DeleteConfirmed in 1 controller

Is it possible to have 2 ActionResult DeleteConfirmed in 1 controller?
I have 2 different views that I want to delete.
Thanks,
EB
[HttpPost, ActionName("DeleteLink")]
public ActionResult DeleteConfirmed(int id)
{
Link link = db.Links.Find(id);
db.Links.Remove(link);
db.SaveChanges();
return RedirectToAction("OutOfBank");
}
It seems that you want to overload DeleteConfirmed action. You can use the attribute if you want your code to do overloading.
[ActionName("MyOverloadedName")]
But, you'll have to use a different action name for the same http method.
So it's just semantics at that point. Would you rather have the name in your code or your attribute?
Code Example:
public class HomeController : Controller
{
public ActionResult GetEmpName()
{
return Content("This is the test Message");
}
[ActionName("GetEmpWithCode")]
public ActionResult GetEmpName(string EmpCode)
{
return Content("This is the test Messagewith Overloaded");
}
}
Phil has an article related to this: http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx

ASP.NET MVC - Routing Structure

I have an ASP.NET MVC 4.5 app. In this app, I have two controllers: Parent and Children. The look something like this:
[RoutePrefix("dashboard/parents")]
public partial class ParentsController : Controller
{
public ActionResult Index()
{
return View();
}
[Route("add")]
public ActionResult Add()
{
return View();
}
}
[RoutePrefix("dashboard/children")]
public partial class ChildrenController : Controller
{
public ActionResult Index()
{
return View();
}
[Route("add")]
public ActionResult Add()
{
return View();
}
}
At this time, these controllers work how I want. However, in my ChildrenController, I want to add something like an overload to the add route. In other words, I'd like for the user to be able to visit: /dashboard/parents/{parentId}/children/add. This URL would be used to add a child to a specific parent. My question is, how do I update my controllers to allow for this type of scenario?
thank you!
I think what you are looking for the is "~" to override your default routeprefix.. The following example is taken from the asp.net website which tells you how to accomplish the task.
[RoutePrefix("api/books")]
public class BooksController : ApiController
{
// GET /api/authors/1/books
[Route("~/api/authors/{authorId:int}/books")]
public IEnumerable<Book> GetByAuthor(int authorId) { ... }
// ...
}

Binding in ASP.NET MVC

My question is about binding in MVC. Could you please help me with it?
My controller:
public class TestController : Controller
{
//
// GET: /Test/
[HttpGet]
public ActionResult Index()
{
return View(new TestModel());
}
public ActionResult Index(TestModel test)
{
return View(test);
}
}
My View:
#model MvcApplication1.Models.TestModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(x => x.test) // or x.Test
<input type="submit" value="Set"/>
}
My model:
public class TestModel
{
public string test { get; set; } // or Test{get;set;}
}
The problem is connected with the name of parameter "test" in controller as I understand. I have just changed it to "model" and the binding is working. But it is not working in original state (the name of parameter is 'test'), 'test' parameter is null.
Please give me understand why the binding is not working in current example. Thank you a lot!
You need an [HttpPost] attribute on your second method. You also cannot use test as your variable name, as it is the same name as the property of the class you're attempting to bind to; the ModelBinder fails to determine which to use. Your code would look as follows:
public class TestController : Controller
{
//
// GET: /Test/
[HttpGet]
public ActionResult Index()
{
return View(new TestModel());
}
//
// POST: /Test/
[HttpPost]
public ActionResult Index(TestModel testModel)
{
return View(testModel);
}
}

asp.net mvc controller with multiple lists and "return to list" link

If you have 5 list views in a controller and in each list you can go to edit, details or delete.
On the edit, details and delete page youo have a link 'return to list'.
What's the best method to 'remember' to which list action you must return?
As a solution I've put some info like CurrentAction in the ViewModel and used that in the View. But if you want to use this with different controllers instead of one...
(You can use a Currentcontroller, CurrentArea, but that's not a 'beautifull' solution)
public class MyController : Controller
{
public ActionResult Index()
{
...
}
public ActionResult List2()
{
...
}
public ActionResult List3()
{
...
}
public ActionResult List4()
{
...
}
public ActionResult Create(...)
{
...
}
[HttpPost]
public ActionResult Create(...)
{
...
}
public ActionResult Edit(...)
{
...
}
[HttpPost]
public ActionResult Edit(...)
{
...
}
public ActionResult Delete(...)
{
...
}
[HttpPost]
public ActionResult Delete(...)
{
...
}
}
thanks
Filip
You can use Request.UrlReferrer Property to examine from where did user come to delete ot edit screens.Then bind url to return to list command.
You can set TempData["ReturnUrl"] in your caller action and then use it to set the url of return to list hyperlink.

Resources