Redirecting to a controller in SpringMvc - spring-mvc

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.

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***);
}
}

Define a base rest controller in spring boot?

Originally I just had MyRestController
#CrossOrigin(origins = "*")
#RestController
public class MyRestController {
#RequestMapping(value = "/v1/endpoint", method = {RequestMethod.GET})
public ResponseEntity<Object> endpoint(HttpServletRequest request,
HttpServletResponse response) {
// etc - duplicate code across controllers with the one
// difference of a single function call and its corresponding params
}
}
Then I realized that a lot of the functionality was reused across 6 other controllers so I consolidated them using an abstract BaseController
abstract class BaseController {
public ResponseEntity<Object> run(String path, String[] params) {
Object result = null;
switch (path.toLowerCase()) {
// case for each path
case MY_PATH:
result = someService.myPath(param[0]);
break;
case MY_OTHER_PATH:
result = someService.myOtherPath(param[0], param[1]);
break;
default:
System.out.println("No");
throw new Exception();
}
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
and then I changed the class header for MyRestController to
public class MyRestController extends BaseController {
and this worked!
My questions are:
How come I couldn't move the CrossOrigin from MyRestController to BaseController ?
I was told to use an abstract class. Does this help at all in this use case?
I replaced the duplicate try / catch with a single function using the path in a switch statement to use the correct method with the correct params. This seems hackish... Is there a better way to do this?
Thanks
Looking at the documentation for the annotation CrossOrigin https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/CrossOrigin.html
This is why it didn't work is because your BaseController doesn't have any methods to add to the RequestMappingHandlerMapping so that is why it didn't work.
As far as the BaseController being abstract it is not necessary unless you have a method that you want your extending controllers to overwrite.
Update about Switch
That is really up to you depending on how many controller methods are going to fall into each case. If multiple methods fall into the MY_PATH case then I believe you are ok, but I can see where the cases could turn into a very lengthy switch statement. It's really up to you as the maintainer. In my opinion, I would break the switch statement cases into different methods and let the controller that extend call that method. But that is personal preference.

404 Not Found when accessing a Web API method

I need this method to return an integer value:
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpPost("ByPayment")]
public int Payment(string accountId, string mount, string shenase)
{
return 21;
}
}
When I go to the following address:
http://localhost:1070/api/values/Payment/ByPayment?accountId=258965&mount=85694&shenase=85456
I get the following error:
What's the problem? And how can I solve it?
I thing you wanted to send Get request with query string parameters.
1. Change the 'HttpPost' to 'HttpGet'
[HttpPost("ByPayment")] to [HttpGet("ByPayment")]
2. Also change your request url, Its not correct.
http://localhost:1070/api/values/Payment/ByPayment?accountId=258965&mount=85694&shenase=85456
to
http://localhost:1070/api/Values/ByPayment?accountId=258965&mount=85694&shenase=85456
Updated code
[Route("api/[controller]")]
public class ValuesController : Controller
{
[HttpGet("ByPayment")]
public int Payment(string accountId, string mount, string shenase)
{
return 21;
}
}
I suggest please read this tutorial to understand the basic of webapi.
There could be more reasons why you get the 404. But there is one thing that's definitely wrong - you are sending GET requests to a method that's marked with [HttpPost("ByPayment")] (which means it only responds to POST requests.
I don't know what you intended to do but you either have to change it to [HttpGet("ByPayment")] or use a REST client that can make POST requests (e.g. REST Easy.
Other reason could be that your controller has a wrong name. It should be called PaymentController.

ASP.Net WebApi: Invalid URL generated in BeginForm

I'm beginning to use WebApi and I'm having an issue with a URL being incorrectly generated
I have an ApiController like this:
public class EntriesController : ApiController
{
public HttpResponseMessage Post(Entry entry)
{
...
}
}
And I was trying to create a standard controller (i.e. not webapi) in the same project to test this api (I already tested the api with fiddler and everything is ok there).
I assumed I could use the standard HTML helpers like this:
#using (Html.BeginForm("Post", "Entries"))
However this generates the following markup:
<form action="/Entries/Post" method="post">
and I expected it to generate
<form action="/api/Entries" method="post">
What is the correct way to generate the API url from a view?
I am using the default api and controller routes.
Thanks
#using (Html.BeginForm("Post", "Entries"))
You can not put WebAPI controller and method in MVC BeginForm like above. You need to pass MVC Controller and action to the BeginForm.
You can create a WebAPI EntriesController instance in your MVC controller, then use this instance to call the WebAPI method. See below:
//MVC Controller
public class EntriesController : Controller
{
[HttpGet]
public ActionResult Entries()
{
return View();
}
[HttpPost]
public ActionResult Entries(SomeModels model)
{
if (ModelState.IsValid)
{
var api = new EntriesController(); // Create WebAPI instance Here
api.Post(model.entry);
return RedirectToAction("Index", "Home");
}
return View();
}
}
This is technically possible by doing:
#using (Html.BeginForm("Post", "api/Entries"))
Don't forget, the "Post" value in the .BeginForm() extension method doesn't mean anything to an out-of-box Web Api route setup. Only the url and HTTP action matter (and any additional values on the URL for method overloading)
You would need to use BeginRouteForm as link generation to Web API routes always depends on the route name. Also make sure to supply the route value called httproute as below.
#using (Html.BeginRouteForm("DefaultApi", new { controller="Entries", httproute="true" }))

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

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.

Resources