I have the following custom route
routes.MapRoute("custom", "Groups/{groupname}/{action}/{id}", new { controller = "Groups", action = "Index", id = UrlParameter.Optional });
This custom route is to achieve the following url schema
Groups/pokerclub/members/ - list all the members of pokerclub group.
Groups/pokerclub/members/bob - list member details of bob.
I tried the following but it doesnt work. it confuses asp .net mvc of which action to select.
public ActionResult Members(string groupName, string id)
{
return View();
}
public ActionResult Members(string groupName)
{
return View();
}
There are two possible solutions that i could think of:
Have different action name. e.g. Memberlist action and member action.
Handle this in the view using simple if statement.
I very much want to maintain my url scheme. thus, as per my original question, how to have two different views associated to one action? Thanks.
RWendi
You can only have one action, but you can perform whatever logic you want inside that action, and you can call views by name:
return View("MyView");
In your example, you would simply return a different view if the id field was null.
where it says return View(); It takes parameters and you can get it to use whatever view you would like
return View("Members", model);
you can use different methods:
[HttpGet]
public ActionResult Members(string groupName, string id)
{
return View();
}
[HttpPost]
public ActionResult Members(string groupName)
{
return View();
}
Related
I have an action method that goes like so:
// GET: admin/cms/add-page
[HttpGet]
[ActionName("add-page")]
public ActionResult AddPage()
{
return View("AddPage");
}
// POST: admin/cms/add-page
[HttpPost]
[ActionName("add-page")]
public ActionResult AddPage(PagesVM pagesVM)
{
...
return RedirectToAction("AddPage");
}
But the redirect redirects to standard url and not the actual and different ActionName - it should redirect to mysite/admin/cms/AddPage instead of mysite/admin/cms/add-page
if you want to return to the same view and keep the form values use:
return View(pagesVM);
if you want to return the same view with empty values use:
return View(new PagesVM()):
ActionResult is the base class for the various return types to View in MVC. So your action must return an ActionResult or a class derived from it in order to work.
so we can use
public ContentResult Index()
{
return Content("Hello world");
}
or for example
public ViewResult Index()
{
return View();
}
or ActionResult
public ActionResult Index()
{
if (ViewBag.Hello = "World")
return Json("");
return PartialView();
}
BUT also is possible use string !!!
public string Index()
{
return "Hello World";
}
WHY is than not possible return integer to view? (Or maybe it is?)
public int Index()
{
return 4;
}
and not possible return some entity to view (Or maybe it is?)
public User Index()
{
return new User();
}
My question is : What happening behind scene when we want to render view?
I agree that this is quite a broad question, but I wanted address and answer a few of the points you raised in your question.
You can return an int, string or object from your action method and it will simply return the object's string representation as the result.
Therefore you don't have to return an object of type ActionResult in order for it to work, but the ActionResult enables useful functionality through it's various implementations so that ASP.NET MVC Framework can handle different scenarios straight out of the box.
Such as returning views and handling the ViewModel you want to pass to your view:
return View(); // Default view without view model
return View(viewModelObject); // Default view with a view model
Returning views based on your routing information:
return View("viewName", viewModelObject);
Performing redirects to another page, using your routing information:
return RedirectToAction(actionName, controllerName);
Returning a page with specific status codes:
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
Returning JSON instead of a view:
return JsonResult(myObject);
All of the above examples do different things, return different types of results and handle your objects for you so that you don't have to code the behaviour yourself - they're ready for you to use.
Another handy thing is that you can create your own implementations of ActionResult to create your own behaviour, so it's very flexible in that regard.
I agree with #Daniel J.G. that you should do some more reading on how ASP.NET MVC hangs together and it will become a lot more clear to you.
I am using MVC 4, and I have the following:
[HttpGet]
public ActionResult SomeForm(modelType model = null)
{
if(model != null)
return View(model);
return View(getModelFromSomewhere());
}
[HttpPost]
public ActionResult SomeForm(modelType model)
{
if(isValid())
doSomething();
else
return SomeForm(model) // Line in Question
}
However, obviously, I am getting an ambiguous method error on "Line in Question". I'm wondering if anyone has an elegant solution to be able to specify to return specifically the [Get] method of the same name?
Thank you!
You can't have methods with the same signature as you've pointed out already. In C# it also means you can't distinguish functions by just return type - so you must use different names if parameters are same (again default values are ignored when matching of signatures).
If you want separate GET and POST handler - use different names of methods and ActionNameAttribute to name the action:
[HttpGet]
[AciontName("SomeForm")]
public ActionResult SomeFormGet(modelType model = null) ...
[HttpPost]
[AciontName("SomeForm")]
public ActionResult SomeFormPost(modelType model) ...
make it compile...
[HttpPost]
public ActionResult SomeForm(modelType model, FormCollection fc)
{
if(isValid())
doSomething();
else
return SomeForm(model) // Line in Question
}
If you are using http get method you are waiting that browser will send you serialized model as a string query. For example, you are waiting url like
http://example.com?name=Andrew&type=Worker&field1=param1&field2=param2&....
It is common practice to use only id in your get method, so you can do it like this:
[HttpGet]
public ActionResult SomeForm(int id)
{
var model = FindModelById(id);
if(model != null)
return View(model);
return View(getModelFromSomewhere());
}
If you are looking for an elegant solution, it will be more elegant in architecture
I was looking for a way to redirect with POST and the solutions I've found suggest simply using the action's name I want and fill the params. All of this within the same controller (let's call it Home)
[HttpPost]
public ActionResult Zoro(NameOfMyModel model, string stringName)
{
//Do whatever needs to be done
return Foo("bar",123);
}
[HttpPost]
public ActionResult Foo(string Name, int Age)
{
//Code here that use the params
return View();
}
So that works great except that when you look at the url, it doesn't show /Home/Foo, it shows /Home/Zoro. Can I fix this without using RedirectToAction? If I use it, I get this: Home/Foo?Name=bar&Age=123 Which I don't want.
Instead of calling directly calling Foo() use RedirectToAction() with this overload of it.
The way you doing calls the action on server but not actually redirects, if you want the url to change you have to redirect to the action:
return RedirectToAction("Foo", new {Name = "bar", Age = 123});
UPDATE:
As in comments mention how to keep the data temporarily ,you can use TempData[] for it:
TempData["Name"] = bar";
TempData["Age"] = 123;
return RedirectToAction("SomeAction");
and in that action you can get it from TempData:
public ActionResult SomeAction()
{
string Name = TempData["Name"] as string;
int Age - TempData["Age"] as int;
return View();
}
NOTE:
Note that RedirectToAction() only works with actions which are HttpGet, it will not work with HttpPost actions.
I want to create a url like that below:
www.mywebapp.com/Users/Profile/john
I have the UsersController controller and the Profile action, which returns a ViewResult to the Profile page.
I've created a route to manage it:
routes.MapRoute(
name: "ProfileRoute",
url: "Users/Profile/{username}",
defaults: new { controller = "Users", action = "Profile", username = UrlParameter.Optional }
);
The first question is: If i change {username} by {id}, it works. When I put {username} like parameter, the action gets NULL in the parameter. Why this?
Here's my action called Profile:
[HttpGet]
public ActionResult Profile(string id) {
if (UsersRepository.GetUserByUsername(id) == null) {
return PartialView("~/Views/Partials/_UsernameNotFound.cshtml", id);
}
return View(id);
}
I've added a View page to show the user profile. However, when the method ends its execution, I got another error:
The view 'john' or its master was not found or no view engine supports the searched locations.
The following locations were searched:
~/Views/Users/john.aspx
~/Views/Users/john.ascx
...
The second question is: The page I have to show is Profile, not a page with the username's name. Why is it happening?
You are getting this error because you are passing a string (id) to the View function, this overload searches for a view with the name passed in the string (in this case the username).
if you are simply trying to pass the username directly to the view you can use something like a ViewBag, so your code should look like this:
public ActionResult Profile(string id) {
if (UsersRepository.GetUserByUsername(id) == null) {
return PartialView("~/Views/Partials/_UsernameNotFound.cshtml", id);
}
ViewBag.Username=id;
return View();
}
I might be reading this incorrectly, but if you change the name of the required parameter from
id to username, it shouldn't return null
[HttpGet]
public ActionResult Profile(string username) {
if (UsersRepository.GetUserByUsername(username) == null) {
return PartialView("~/Views/Partials/_UsernameNotFound.cshtml", id);
}
return View(username);
}