Let's say I have two create action methods, one for get method, one for post method:
[HttpGet]
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create()
{
return View();
}
If I just add a view to Get method, so there is no view for Post action method, so when I invoke the post method of Create, why I still get the view that belongs to the get method?
When you create a View from a method, this view belongs to all methods with the same name and that share the same class.
If you want to call another view (In this case, from the post method), just use
return View("nameOfTheView");
The path to the view is inferred from the name of the controller and the name of the controller action.
If you prefer, you can be explicit about the view. The following line of code returns a view named Foo:
return View("Foo");
so, you should specify the name of view that you want to return
Related
I'm following this tutorial on .Net controllers, and it says "imagine that you enter the following URL into the address bar of your browser: http://localhost/Product/Index/3. In this case, a controller named ProductController is invoked."
What I Want To Know:
In order to successfully hit http://localhost/Product/Index/3, do you need a controller called ProductController specifically?
No, it is not necessary. You can use Route Attribute.
[Route("new-name-for-product")]
public class ProductController{
}
now you have to use http://localhost/new-name-for-product/Index/ this URL to invoke ProductController.
If you want to use one or more parameters with this URL you have to use different route templates for ActionMethod. Example below.
[Route("new-name-for-product")]
public class ProductController
{
// http://localhost/new-name-for-product/3/ will show product details based on id
// http://localhost/new-name-for-product/Index/3/ will show product details based on id
[HttpGet]
[Route("/{id}")]
public IActionResult Index(int id)
{
// your code
}
// you can use a different action method name.
// http://localhost/details/3/ will show product details based on id
// but parameter name (Ex: id) and the id inside route template the spelling must be the same.
[HttpGet]
[Route("details/{id}")]
public IActionResult GetById(int id)
{
// your code
}
}
It depends. In ASP.Net Core, routing can be configured either as conventional routing or as attribute routing.
Conventional routing is configured as below:
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
Here, the first path segment maps to the controller name,
the second maps to the action name,
the third segment is used for an optional id used to map to a model entity.
As a convention, controller file name is usually same as controller class name.
Hence, In conventional routing, url will match with filename.
The URL http://localhost/Products/Index matches below action method in ProductsController.
[Route("[controller]")]
public class ProductsController : Controller
{
[HttpPost("Index")] // Matches 'Products/Index'
public IActionResult Index()
{
return View();
}
}
Attribute Routing
With attribute routing the controller name and action names play no role in which action is selected.
Hence, it is independent of file name.
The URL http://localhost/Items/All matches below action method in ProductsController.
public class ProductsController : Controller
{
[Route("Items/All")]
public IActionResult Index()
{
return View();
}
}
Similarly, [Route] attribute can be added at both Controller and action methods. The same URL http://localhost/Items/All matches the action method shown below:
[Route("Items")]
public class ProductsController : Controller
{
[Route("All")]
public IActionResult Index()
{
return View();
}
}
For more details, you can refer to microsoft docs at https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-3.1
What are the differences between HTTPGET method and HTTPGET("{id}") method?
What is the API method that is used to update table columns?
[HttpGet]
public IActionResult Get()
{
return new JsonResult(users);
}
// GET api/values/5
[HttpGet("{id}")]
public IActionResult Get(string id)
{
return new JsonResult(response);
}
You should take a look at Attribute Routing in Web API.
The first method is routing to a clean api:
/api/controller
The second specifies route value in the attribute and will be called via the following url:
/api/controller/5
The second one is normally used to update existing queries, as you specify specific value in the route whilst the first specifies nothing.
A lot of my plain content is in the database, accessed by a custom CMS. Around the application I display simple "thank you" messages, etc. which consist of a controller action (simplified):
public ActionResult DetailsUpdated()
{
return View();
}
and my view:
#Html.GetContent("DetailsUpdated")
I have quite a few of these and its quite annoying having a lot of view files with one-liners in. I want to be able to return that content as a View, I can do return ContentResult(ContentRepository.GetContent("KEY")); but this returns as plain-text and there is no master view rendered.
So, basically, grab the content from the DB via ContentRepository.GetContent("KEY") (returns a string) and inject it into a master view, where RenderBody() is called. I'd like to have a custom ActionResult so I can just do:
public ActionResult DetailsUpdated()
{
return DbContentResult();
}
and then the DbContentResult ActionResult will find the content key relative to the action and controller name, go to the database and retrieve the content and display it within its master view, no physical file view needed. Is this possible?
You may have one view file and refer to that view file from several actions:
public class FooBarController : Controller {
public ViewResult Foo() {
return View("FooView", ContentRepository.GetContent("KEY"));
}
}
In this case, you will be able to render the view whose path is ~/Views/Shared/FooView.cshtml (unless you override the default convention of course).
Edit:
As you indicated, you can make a custom ViewResult which does this for you:
public class DbContentResult : ViewResult {
public DbContentResult() {
this.ViewName = "FooView";
this.ViewData.Model = "Foo Model";
}
}
Usage:
public ActionResult Index() {
return new DbContentResult();
}
Or even better, write an extension method for Controller class which integrates with DbContentResult:
public static class ControllerExtensions {
public static ViewResult DbContentResult(this Controller controller) {
return new DbContentResult();
}
}
Usage:
public ActionResult Index() {
return this.DbContentResult();
}
for more detail about creating custom actionresult go here:-
http://www.professionals-helpdesk.com/2012/06/create-custom-actionresult-in-mvc-3.html
What is the difference between ViewResult() and ActionResult() in ASP.NET MVC?
public ViewResult Index()
{
return View();
}
public ActionResult Index()
{
return View();
}
ActionResult is an abstract class that can have several subtypes.
ActionResult Subtypes
ViewResult - Renders a specifed view to the response stream
PartialViewResult - Renders a specifed partial view to the response stream
EmptyResult - An empty response is returned
RedirectResult - Performs an HTTP redirection to a specifed URL
RedirectToRouteResult - Performs an HTTP redirection to a URL that is determined by the
routing engine, based on given route data
JsonResult - Serializes a given ViewData object to JSON format
JavaScriptResult - Returns a piece of JavaScript code that can be executed on the client
ContentResult - Writes content to the response stream without requiring a view
FileContentResult - Returns a file to the client
FileStreamResult - Returns a file to the client, which is provided by a Stream
FilePathResult - Returns a file to the client
Resources
What's the difference between ActionResult and ViewResult for action method? [ASP.NET Forums]
ActionResult is an abstract class.
ViewResult derives from ActionResult. Other derived classes include JsonResult and PartialViewResult.
You declare it this way so you can take advantage of polymorphism and return different types in the same method.
e.g:
public ActionResult Foo()
{
if (someCondition)
return View(); // returns ViewResult
else
return Json(); // returns JsonResult
}
It's for the same reason you don't write every method of every class to return "object". You should be as specific as you can. This is especially valuable if you're planning to write unit tests. No more testing return types and/or casting the result.
ViewResult is a subclass of ActionResult. The View method returns a ViewResult. So really these two code snippets do the exact same thing. The only difference is that with the ActionResult one, your controller isn't promising to return a view - you could change the method body to conditionally return a RedirectResult or something else without changing the method definition.
While other answers have noted the differences correctly, note that if you are in fact returning a ViewResult only it is better to return the more specific type rather than the base ActionResult type. An obvious exception to this principle is when your method returns multiple types deriving from ActionResult.
For a full discussion of the reasons behind this principle please see the related discussion here: Must ASP.NET MVC Controller Methods Return ActionResult?
In the Controller , one could use the below syntax
public ViewResult EditEmployee() {
return View();
}
public ActionResult EditEmployee() {
return View();
}
In the above example , only the return type varies . one returns ViewResult whereas the other one returns ActionResult.
ActionResult is an abstract class . It can accept:
ViewResult , PartialViewResult, EmptyResult , RedirectResult , RedirectToRouteResult , JsonResult , JavaScriptResult , ContentResult, FileContentResult , FileStreamResult , FilePathResult etc.
The ViewResult is a subclass of ActionResult.
In Controller i have specified the below code with ActionResult which is a base class that can have 11 subtypes in MVC like:
ViewResult, PartialViewResult, EmptyResult, RedirectResult,
RedirectToRouteResult, JsonResult, JavaScriptResult, ContentResult,
FileContentResult, FileStreamResult, FilePathResult.
public ActionResult Index()
{
if (HttpContext.Session["LoggedInUser"] == null)
{
return RedirectToAction("Login", "Home");
}
else
{
return View(); // returns ViewResult
}
}
//More Examples
[HttpPost]
public ActionResult Index(string Name)
{
ViewBag.Message = "Hello";
return Redirect("Account/Login"); //returns RedirectResult
}
[HttpPost]
public ActionResult Index(string Name)
{
return RedirectToRoute("RouteName"); // returns RedirectToRouteResult
}
Likewise we can return all these 11 subtypes by using ActionResult() without specifying every subtype method explicitly.
ActionResult is the best thing if you are returning different types of views.
To save you some time here is the answer from a link in a previous answer at https://forums.asp.net/t/1448398.aspx
ActionResult is an abstract class, and it's base class for ViewResult class.
In MVC framework, it uses ActionResult class to reference the object your action method returns. And invokes ExecuteResult method on it.
And ViewResult is an implementation for this abstract class. It will try to find a view page (usually aspx page) in some predefined paths(/views/controllername/, /views/shared/, etc) by the given view name.
It's usually a good practice to have your method return a more specific class. So if you are sure that your action method will return some view page, you can use ViewResult. But if your action method may have different behavior, like either render a view or perform a redirection. You can use the more general base class ActionResult as the return type.
So far I still have the standard routing. What I tried to do is
public Foo : Controller
{
public ActionResult Index(int id)
{
return View("List", repo.GetForId(id));
}
public ActionResult Index()
{
return View("List", repo.GetAll());
}
}
The URL I entered was
localhost/Foo/Index.
I was under the asumption that it was smart enough to figure out which method I wanted. All I get though is an error telling me that the call is ambigous. From reading the route tutorial I thought that this would work. What am I missing?
Sorry:
Duplicate. I am voting to close.
Method overloading (two actions with the same name) resolution is based on the HTTP verb. This means that if you want to have two actions with the same name you need to differentiate them by the HTTP verb they accept:
public ActionResult Index(int id)
{
return View("List", repo.GetForId(id));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index()
{
return View("List", repo.GetAll());
}
Thus when you call GET /Home/Index the first action will be invoked and when you call POST /Home/Index the second one will be invoked.
Also note that you should probably use nullable integer as the id argument because if no parameter is passed in the request, the model binder will fail.
A RESTful way to handle this, following conventions that I would suggest you is this:
public ActionResult Index()
{
return View(repo.GetAll());
}
public ActionResult Show(int id)
{
return View(repo.GetForId(id));
}
which will allow you to handle both /Home/Index and /Home/Show/10 requests. You probably will have different views as well because the first one will be strongly typed to IEnumerable<T> while the second one to T.