Is there any other base class which looks for a view other than System.Web.Mvc.ViewResultBase - asp.net

On ASP.NET MVC 3, assume that we have following controller action:
public ActionResult Index() {
ViewBag.Message = "Foo Bar";
return View();
}
Here, Index method is returning ViewResult instance which implements System.Web.Mvc.ViewResultBase class. Because of the fact that we return instance of a ViewResult class, system tries to find a proper view file in order to generate an output. If it cannot find it, it will throw an exception.
My question is this:
Is there any other base class which looks for a view other than System.Web.Mvc.ViewResultBase?
In plain English, do we have to return a class, which implements System.Web.Mvc.ViewResultBase class, from controller action in order to render the result with a view?
EDIT
Also, as you see here I am telling that I will return a type of ActionResult which is the base, base class so to speak. When you look at the end, I am returning an instance of ViewResult.
How does framework handle that? Does it try to cast every controller action result to ViewResultBase class on the fly? I am really curious about this part especially.

The ControllerActionInvoker class is responsible for executing the controller actions. After finding and executing the action it looks for the action return type:
If the return type is void then it the creates a EmptyResult
If the return type anything but ActionResult then it converts the returned value to string and creates a ContentResult with that string.
So finally a result of an action is always an instance of the ActionResult class which declares the following method:
public abstract void ExecuteResult(ControllerContext context);
Then the ControllerActionInvoker basically calls this ExecuteResult method to allow for the ActionResult to write to the Reponse. There is where in the case of ViewResultBase the view rendering is happening.
To answer your fist question in MVC3 only the descandants of the ViewResultBase class are rendering views.

Related

get or pass values from jsp to spring mvc controller with #RequestParam("VIEW") annotation

Hi everyone I'm trying to get or pass the values from my JSP to my controller because I want to write a method whose main function will be to save a new user in the database but I got an error like this:
(((java.lang.IllegalStateException: Mode mappings conflict between method and type level: [/myPath] versus [VIEW])))
I guess this two annotations, first in the class declaration #RequestMapping("VIEW") and the second in the method declaration for save the new user
#RequestMapping(value="/saveUser", method = RequestMethod.POST)
are in conflict by the use of the same annotation in tow times at the same controller but I have to say that I´ve been tried to remove the #RequestMapping annotation in the class declaration and after that, I get a different error like this:
(((java.lang.IllegalStateException: No portlet mode mappings specified - neither at type nor at method level)))
I don't know if I can use as many necessary controllers for differents operations as I will need, if I can, I will be happy to know the correct way to implement with this technique
Here is my controller:
#Controller
#RequestMapping("VIEW")
public class UsersController {
User currentUser = null;
#RenderMapping
public ModelAndView view(RenderRequest request, RenderResponse response)throws Exception {
ModelAndView modelView = new ModelAndView();
UserDTO usuarioAdd = new UserDTO();
//blah, blah, blah...
return modelView;
}
#RequestMapping(value="/saveUser", method=RequestMethod.POST)
public void saveUser(HttpServletRequest request) {
logger.info("***SAVE USER***);
System.out.println("***SAVE USER***);
}
}

Redirecting to a controller in SpringMvc

I have a class which has multiple controller in it and from one of the controller i want to call another controller which is in different class and when the particular controller is called that controller will create the view.
my codes are
class one // class from which controller will be called
#Controller
#RequestMapping(value="/register")
public class PatientController {
#RequestMapping(value="/demo1", method=RequestMethod.GET)
public String demo1(){
System.out.println("Demo1 method.....");
return "redirect:user/dashboard";
}
}
Class second // controller of this class to be called
#Controller
#RequestMapping("/user")
public class UserDasboardController {
#RequestMapping(value="/dashboard", method=RequestMethod.GET)
public String get(ModelMap model){
return "userdashboard";// returning view
}
}
after the first controller is called gives url as ".../register/user/dashboard"
however it should give url as"..../user/dashboard".
please suggest how can I achieve this.
Or there is any other way of doing same thing.
when using redirect for the same controller file we can use this as
return "redirect: controllerName"
if you want to call the controller of another class you have to call it as using / before it so that will be as
"redirect:/firstController/yourSubController"
Hope this helps.
Another solution is: MvcUriComponentsBuilder MvcUriComponentsBuilder docs
There are some great methods like: fromMethod(), fromController() and more.
You can receive proper redirection path to another method/controller automatically.
Example - redirect to another controller:
final UriComponentsBuilder uriComponents = MvcUriComponentsBuilder.fromController(WheredoYouWantToRedirectController.class);
final String path = uriComponents.build().getPath();
return REDIRECT_PREFIX+path;
In the same way you may work with redirection to methods.
MvcUriComponentsBuilder helps to reduce errors connected with redirections.
Please check documentation for more info.

How exactly does a .net MVC controller know which View() to return?

When I want to call a new page in .net, say the "About.cshtml" page, I use the following code in the HomeController:
public ActionResult About()
{
ViewBag.Title = "About";
return View();
}
To call it I'd use a link to "/Home/About". And if I wanted to create a new page called "Contact.cshtml", for example, I'd copy the above and replace About with Contact.
I know that the route in "/Home" calls the HomeController. But how, exactly, does that controller know to return the About.cshtml page? I assume it's based on the name of the function. But this doesn't sound right to me. About() isn't an HTTP verb like Get() or Post(), and the name of the function normally shouldn't define what it does, unless it already existed.
Also, when exactly is View() defined, and when is it assigned to the About.cshtml page?
Finally, is there an attribute that would allow me to return the About.cshtml page with a different function name (as I can set a function to respond to Get with the [HttpGet] attribute)?
But how, exactly, does that controller know to return the About.cshtml page?
Because the action method name is About:
public ActionResult About()
The route found that method by the URL:
/Home/About
If the URL didn't include the action:
/Home
Then it would look for a default action. Normally this is Index(), as configured by the default route mapping:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
Note how a default value is defined for both controller and action if none is provided on the URL.
the name of the function normally shouldn't define what it does
Why on Earth not? A function name should exactly define what that function does.
Also, when exactly is View() defined
It's in the base controller class.
Finally, is there an attribute that would allow me to return the About.cshtml page with a different function name
Not an attribute per se, but you can specify the view name when calling View():
return View("SomeOtherView");
only to explain a few more (the David's response is so good), View() is an object of type ViewResultBase, in class Controller;
protected internal ViewResult View()
{
return View(viewName: null, masterName: null, model: null);
}
ViewResultBase has a method ExecuteResult() that receives a parameter of type ControllerContext (this parameter has the info about the request) and inside this method, if the name of the view is null, the view name is established based on the url (read the explain of David about the routing) that is called accesing to the RouteData:
public override void ExecuteResult(ControllerContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (String.IsNullOrEmpty(ViewName))
{
ViewName = context.RouteData.GetRequiredString("action");
}
....
}
Here, if you watch the RouteData you can view that the called action is Index, and this value is set to the ViewName property:
Regards,

What does it mean when Spring MVC #Controller returns null view name?

I downloaded the code for the Spring MVC 3 Showcase. One thing puzzles me (well, more than one), why does this (edited for concision) sample return null?
#Controller
#RequestMapping("/form")
public class FormController {
#RequestMapping(method=RequestMethod.POST)
public String processSubmit(#Valid FormBean form,
BindingResult result,
WebRequest webRequest,
HttpSession session, Model model) {
if (result.hasErrors()) {
return null;
} else {
session.setAttribute("form", form);
return "redirect:/form";
}
}
}
If a controller returns a null view name, or declares a void return type, Spring will attempt to infer the view name from the request URL.
In your case, it will assume the view name is form, and proceed on that assumption.
It does this using an implementation of RequestToViewNameTranslator, the default implementation of which is DefaultRequestToViewNameTranslator, the javadoc for which explains the exact rules it applies.
AnnotationMethodHandlerAdapter.invokeHandlerMethod() takes care of invoking handler methods. Here, a ModelAndView will be retrieved via ServletHandlerMethodInvoker.getModelAndView().
In your case, getModelAndView() gets provided the handler method's null return value. The getModelAndView() method checks for the return value's type, but as in Java null is never an instanceof any class, that method's logic will create a new ModelAndView. A new ModelAndView has initially its view property set to null.
Then later back up the call stack, in DispatcherServlet.doDispatch(), there is a test if the ModelAndView object has a View associated with it ( mv.hasView() ). Because view == null, doDispatch()'s logic calls mv.setViewName(getDefaultViewName(request)). It delegates to the registered RequestToViewNameTranslator, whose default implementation is DefaultRequestToViewNameTranslator. This subclass translates the request URI into a view name, in your case form.
Later in doDispatch(), via render() -> resolveViewName(), this sample's ViewResolvers are provided with the view name form. Only one ViewResolver, InternalResourceViewResolver is used in this sample. Also, this InternalResourceViewResolver was configured in src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml to add the prefix /WEB-INF/views/ and the suffix .jsp to the view name. So in total, it will create a View using the JSP file /WEB-INF/views/form.jsp. Luckily, a JSP file exists at exactly this location.

Strongly typed Update and Create controller actions

I have example code in which the signature of the Create action menthod in the controller looks like this:
[HttpPost]
public ActionResult Create(JobCardViewData viewData)
I have just created a new MVC application and the same signature looks like this:
[HttpPost]
public ActionResult Create(FormCollection collection)
I would prefer to know how to implement my action methods like the top example, or at least how to convert from the FormCollection to a business object without going as low level as using Reflection.
Personally I avoid using FormCollection as it is a collection of magic strings. I would recommend you to always use this signature:
[HttpPost]
public ActionResult Create(JobCardViewData viewData)
and leave the model binder do the job of parsing the request parameters into a strongly typed object (you don't need to resort to reflection or doing anything).

Resources