Return spring mvc Model on Ajax response - spring-mvc

I am having a controller that return model objects like below
model.addAttribute("list", list);
When i click a button ajax call happens and it is goes to controller executing everything and it returns. But i don't know how to access this model object in my jsp on ajax response. When i use alert for success ajax response , I am just seeing a html kind of page.
Please give me some example or reference to achieve this
Thanks in advance
Please find my sample code snippet
Controller.java
#RequestMapping(value='/ajax' value="POST")
Public #ResponseBody String displayDropdown(MyForm myform,Model model) {
//logic to fetch details from DB
List<String> list = fetchFromDB();
model.addAttribute("list" list);
return "ajaxResponse";
}
My JSP
In a button click, having the below ajax call
$.ajax {
url:'/ajax',
type:'POST',
data: $("#myform").serialize();
success:function(data) {
alert(response);
}
}
I want to get my model from this ajax response and use it in my jsp.

I am not sure, but from JSP all model attribute variables are accessible simply using ${attribute_name}. In your case it is ${list}

Maybe you can use
console.info(model)

I am not sure that you can access response with JSP. JSP is the server side and response you receive when the page is already sent to client. The only thing you can try is to use COOKIES. Set response in cookies and then access it from the server.

Yes You can easily get Model data from controller, simply
#RequestMapping(value='/ajax' value="POST")
Public String displayDropdown(MyForm myform,Model model) {
//logic to fetch details from DB
List<String> list = fetchFromDB();
model.addAttribute("list" list);
return "yourjsppage";
}
$.ajax {
url:'/ajax',
type:'POST',
data: $("#myform").serialize();
success:function(data) {
$("#page-wrapper").html( data );
}
}
page-wrapper is your content div in jsp page. this returns all jsp page including your model. in this scenario it is also useful when you want (partial rendering) not wanting to refresh whole page but targeting specific page.

Related

ASP.NET MVC - AJAX how to correct use?

I just started working with ASP.NET after PHP and have a question regarding using AJAX.
What is the correct methodology?
I googled that have Ajax helpers
Or use jquery code for calling methods from controller
Is it ok to return "ready" html code from controllers to view via ajax request?
For example, Now i use the same
$.post('/ControllerName/ActionFromController', { /* some params */ }, function(data){
$("#content_div").html(data);
});
my controller
public ActionResult ActionFromController()
{
// receiving parameters from AJAX request - Request.Form["parameter name"])
// to do something here
string cont = "some result of methjd works - HTML table or something else"
return cont;
}
So is it here any development methodology for using AJAX in asp.net MVC? Or is it ok to use ajax as it described above?
Almost there. The best way to bind your parameters is to strongly type them, which you can do with models. Create a model class:
public class SampleModel
{
public string ParamName1 {get;set;}
public int ParamName2 {get;set;}
}
Make sure your actions accepts this as an input:
public ActionResult ActionFromController(SampleModel model)
And when you send your ajax request specify parameters:
$.post(
'/ControllerName/ActionFromController',
{ "ParamName1": "value", "ParamName2": 1 },
function(data){
$("#content_div").html(data);
}
);
Otherwise what you have look fine.
I would suggest you to get some more information and possible results types:
JsonResult
PartialViewResult - try not to concatenate HTML in the string, return a Partial View which will contain HTML constructed based on model (for example some parameters from the ajax request. Useful resources: Partial View in ASP.NET MVC, Updating an MVC Partial View with Ajax

Alternative to Server.Transfer in ASP.NET Core

I am migrating an ASP.NET application to ASP.NET Core and they have some calls to HttpServerUtility.Transfer(string path). However, HttpServerUtility does not exist in ASP.NET Core.
Is there an alternative that I can use? Or is Response.Redirect the only option I have?
I want to maintain the same behaviour as the old application as much as possible since there is a difference in between Server.Transfer and Response.Redirect.
I see some options for you, depending on your case:
Returning another View: So just the HTML. See answer of Muqeet Khan
Returning another method of the same controller: This allows also the execution of the business logic of the other action. Just write something like return MyOtherAction("foo", "bar").
Returning an action of another controller: See the answer of Ron C. I am a bit in troubles with this solution since it omits the whole middleware which contains like 90% of the logic of ASP.NET Core (like security, cookies, compression, ...).
Routing style middleware: Adding a middleware similar to what routing does. In this case your decision logic needs to be evaluated there.
Late re-running of the middleware stack: You essentially need to re-run a big part of the stack. I believe it is possible, but have not seen a solution yet. I have seen a presentation of Damian Edwards (PM for ASP.NET Core) where he hosted ASP.NET Core without Kestrel/TCPIP usage just for rendering HTML locally in a browser. That you could do. But that is a lot of overload.
A word of advice: Transfer is dead ;). Differences like that is the reason for ASP.NET Core existence and performance improvements. That is bad for migration but good for the overall platform.
You are correct. Server.Transfer and Server.Redirect are quite different. Server.Transfer executes a new page and returns it's results to the browser but does not inform the browser that it returned a different page. So in such a case the browser url will show the original url requested but the contents will come from some other page. This is quite different than doing a Server.Redirect which will instruct the browser to request the new page. In such a case the url displayed in the browser will change to show the new url.
To do the equivalent of a Server.Transfer in Asp.Net Core, you need to update the Request.Path and Request.QueryString properties to point to the url you want to transfer to and you need to instantiate the controller that handles that url and call it's action method. I have provided full code below to illustrate this.
page1.html
<html>
<body>
<h1>Page 1</h1>
</body>
</html>
page2.html
<html>
<body>
<h1>Page 2</h1>
</body>
</html>
ExampleTransferController.cs
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace App.Web.Controllers {
public class ExampleTransferController: Controller {
public ExampleTransferController() {
}
[Route("/example-transfer/page1")]
public IActionResult Page1() {
bool condition = true;
if(condition) {
//Store the original url in the HttpContext items
//so that it's available to the app.
string originalUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}{HttpContext.Request.Path}{HttpContext.Request.QueryString}";
HttpContext.Items.Add("OriginalUrl", originalUrl);
//Modify the request to indicate the url we want to transfer to
string newPath = "/example-transfer/page2";
string newQueryString = "";
HttpContext.Request.Path = newPath;
HttpContext.Request.QueryString = new QueryString(newQueryString);
//Now call the action method for that new url
//Note that instantiating the controller for the new action method
//isn't necessary if the action method is on the same controller as
//the action method for the original request but
//I do it here just for illustration since often the action method you
//may want to call will be on a different controller.
var controller = new ExampleTransferController();
controller.ControllerContext = new ControllerContext(this.ControllerContext);
return controller.Page2();
}
return View();
}
[Route("/example-transfer/page2")]
public IActionResult Page2() {
string originalUrl = HttpContext.Items["OriginalUrl"] as string;
bool requestWasTransfered = (originalUrl != null);
return View();
}
}
}
Placing the original url in HttpContext.Items["OriginalUrl"] isn't strictly necessary but doing so makes it easy for the end page to know if it's responding to a transfer and if so what the original url was.
I can see this is a fairly old thread. I don't know when URL Rewriting was added to .Net Core but the answer is to rewrite the URL in the middleware, it's not a redirect, does not return to the server, does not change the url in the browser address bar, but does change the route.
resources:
https://weblog.west-wind.com/posts/2020/Mar/13/Back-to-Basics-Rewriting-a-URL-in-ASPNET-Core
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/url-rewriting?view=aspnetcore-5.0
I believe you are looking for a "named view" return in MVC. Like so,
[HttpPost]
public ActionResult Index(string Name)
{
ViewBag.Message = "Some message";
//Like Server.Transfer() in Asp.Net WebForm
return View("MyIndex");
}
The above will return that particular view. If you have a condition that governs the view details you can do that too.
I know that this is a very old question, but if someone uses Razor Pages and is looking to a Server.Transfer alternative (or a way to return a different view depending on a business rule), you can use partial views.
In this example, my viewmodel has a property called "UseAlternateView":
public class TestModel : PageModel
{
public bool UseAlternateView { get; set; }
public void OnGet()
{
// Here goes code that can set UseAlternateView=true in certain conditions
}
}
In my Razor View, I renderize a diferent partial view depending of the value of the UseAlternateView property:
#model MyProject.Pages.TestModel
#if (Model.UseAlternateView)
{
await Html.RenderPartialAsync("_View1", Model);
}
else
{
await Html.RenderPartialAsync("_View2", Model);
}
The partial views (files "_View1.cshtml" and "_View2.cshtml"), contain code like this:
#model MyProject.Pages.TestModel
<div>
Here goes page content, including forms with binding to Model properties
when necessary
</div>
Obs.: when using partial views like this, you cannot use #Region, so you may need to look for an anternative for inserting scripts and styles in the correct place on the master page.

How to call JSP from a java Controller

I have a simple J2EE application with Spring.
Now I want from Java controller call another page. For example, I'm in registrazione.jsp, I click on one button, and I call a method in registrazioneController.java.
Now I want from registrazioneController.java, call another page, for example
home.jsp and I want pass any parameter in get.
It is possible?
this is the method that I use when I click the button
registrazioenControlle.java
public ModelAndView internalLoadPage(HttpServletRequest request, HttpServletResponse response, Map model) throws Exception
{
//to do
//call another page for example home.html
request.getRequestDispatcher("home.jsp").forward(request, response);
return new ModelAndView("home", model);
}
I'm try to use this code but no found.
In addition to the answer provided in the comments, you can also use RedirectAttributes, and addAttribute method if you want to append a parameter to URL upon redirect. This will also give you the addFlashAttribute that will store the attributes in the flash scope which will make it available to the redirected page. You can also return a simple string as the view name e.g. like
public String internalLoadPage(RedirectAttributes redirectAttributes) throws Exception
{
redirectAttributes.addAttribute("paramterKey", "parameter");
redirectAttributes.addFlashAttribute("pageKey", "pageAttribute");
return "redirect:/home";
}
this assumes that the view suffix is configured in you view resolver configuration

asp.net mvc Serverside validation no return data

I'm building a validation form in my application. In that form there are two buttons. One to accept and one to reject. When the user press reject the rejection reason field must be provided. I check this serverside.
I first check what button is pressed and then if the field is empty I add a moddel error to the modelstate. But, because all fields in the form are readonly, those are not posted back to the server and therefor when I return the view back to usern there is no data. I'm probably missing something obvious, but cant find what to do. (I know I can make all fields in my form hidden, but due to the large amount of fields this would be really ugly)
This is my code.
[HttpPost]
public virtual ActionResult Validate(string action, Record dto) {
if(action == Global.Accept) {
ciService.Store(dto);
return RedirectToAction("Index", "Ci");
} else {
if(string.IsNullOrEmpty(dto.RejectionReason)) {
ModelState.AddModelError("RejectionReason", "REQUIRED!!!!");
return View("Validate", dto);
}
ciService.Reject(dto);
return RedirectToAction("Index", "Ci");
}
}
You need to recreate the model from the database and then change it to match whatever changes are posted in dto. Then use that combined model in the view.
Instead of passing the DTO back from the browser, I would use a hidden HTML field or a querystring parameter containing the ID that identifies the DTO. Then your POST action method would look something like:
[HttpPost]
public virtual ActionResult Validate(string action, int id)
{
// reload the DTO using the id
// now you have all the data, so just process as you did in your question
if (action == Global.Accept) { ... }
...
}
Your GET method might look something like the following then...
[HttpGet]
public virtual ActionResult Validate(int id)
{
// load the DTO and return it to the view
return View();
}
In this way you have all the data you need within your POST action method to do whatever you need.
You need to have hidden fields corresponding to each property displayed in UI.
e.g.,
#Html.LabelFor(m=>m.MyProperty) - For Display
#Html.Hiddenfor(m=>m.MyProperty) - ToPostback the value to server
If I understand right, the problem is because you don't use input.
To solve your problem insert some input hidden in your form with the value you need to be passed to the controller
#Html.HiddenFor(model => model.Myfield1)
#Html.HiddenFor(model => model.Myfield2)
that should fix the values not passed back to your actions
If you don't need these fields on the server side, simply create a new ViewModel
RecordValidateViewModel and this contains only the fields in it that need to be validated. The model binder will populate then and you will have validation only on the fields in that model rather than all the other fields you don't seem to want there.
If you need them to validate, then post them back to the server. Its not 'ugly' if hidden.

In MVC, how to determine if partial view response was valid (on the client side)?

I am new to MVC, so hopefully my question will be straight forward. I am thinking of a scenario where the user submits a form (that is a partial view) and it undergoes server validation. I am wondering how I will know the result of the validation on the client side (javascript) after the form is submitted. For example, if validation fails I will obviously want to return the partial view again with validation messages set, but if it passes validation I may not necessarily want to return the partial view. I may want to return a json object with a message or hide a div or something. I want to be able to determine the validation result on the client. Is something like that possible? Or can I approach this a different way?
The tricky part with AJAX is that the client and server both have to agree on what's supposed to come back from the server in any circumstance. You have a few options:
Your server will always return HTML, and jQuery will always replace the editor content with the HTML that comes back. If the model is invalid, you return a PartialView result. If the model is valid, you return a <script> tag that tells the page what it needs to do (e.g. close a dialog, redirect to a different page, whatever). jQuery will automatically run any script it finds in the results when it tries to insert them into the DOM.
Your server will always return a JSON object representing what happened. In this scenario, your client-side javascript code has to be complex enough to take the results and modify your page to match. Under normal circumstances, this will mean that you don't get to take advantage of MVC's validation features.
Same as 2, except that you use a custom utility method to render the partial view you want into a string, and you make that entire string part of the JSON that comes back. The javascript code then just has to be smart enough to check whether the JSON shows a valid or invalid result, and if the result is valid, replace the contents of your editor area with the partialview HTML that is returned as part of the JSON object you got back.
Same as 3, except you develop an event-based architecture where all your AJAX requests will always expect to get back a JSON object with one or more "events" in it. The AJAX code can then be consolidated into one method that hands the events off to an Event Bus. The event bus then passes the event information into callbacks that have "subscribed" to these events. That way, depending on what kind of events you return from the server, you can have different actions occur on the client side. This strategy requires a lot more up-front work to put in place, but once it's done you can have a lot more flexibility, and the client-side code becomes vastly more maintainable.
Partial views would not have a Layout page. You may use this code to check if the view is rendered as partial view.
#if (String.IsNullOrWhiteSpace(Layout))
{
// Do somthing if it is partial view
}
else
{
// Do somthing if it is full page view
}
If you are using the MVC Data Annotations for validating your Model, then the controller will have a property called ModelState (typeof(ModelStateDictionary) which as a property of IsValid to determine if your Model passed into the Controller/Action is valid.
With IsValid you can return a Json object that can tell your Javascript what to do next.
Update
Here is a really basic example (USES jQuery):
[SomeController.cs]
public class SomeController : Controller
{
public ActionResult ShowForm()
{
return View();
}
public ActionResult ValidateForm(MyFormModel FormModel)
{
FormValidationResults result = new FormValidationResults();
result.IsValid = ModelState.IsValid;
if (result.IsValid)
{
result.RedirectToUrl = "/Controller/Action";
}
this.Json(result);
}
}
[FormValidationResult.cs]
public class FormValidationResults
{
public bool IsValid { get; set; }
public string RedirectToUrl { get; set; }
}
[View.js]
$(document).ready(function()
{
$("#button").click(function()
{
var form = $("#myForm");
$.ajax(
{
url: '/Some/ValidateForm',
type: 'POST',
data: form.serialize(),
success: function(jsonResult)
{
if (jsonResult.IsValid)
{
window.location = jsonResult.RedirectToUrl;
}
}
});
});
});

Resources