Redirect in ASP.Net MVC4 - ajax

I'm using ASP.Net MVC4 Razor. I'm having a problem with redirection. I wanna redirect the user to the Home controller at the user login(if login is valid).
But my problem is it always come back to the login page even the redirect meythod also fired.
Here is my code..
public class LoginController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult LoginAccess()
{
return RedirectToAction("Index", "Home");
}
}
Login page..
<div class="body_wraper">
<div id="cloud" style="background:url('#Url.Content("~\\Content\\cloud.png")');">
<div id="login_form">
<div class="Three-Dee">Login here..</div>
<table>
<tbody>
<tr>
<td>#Html.Label("Username")</td>
<td></td>
<td>#Html.TextBox("txtUsername")</td>
</tr>
<tr>
<td>#Html.Label("Password")</td>
<td></td>
<td>#Html.Password("txtPassword")</td>
</tr>
<tr>
<td></td>
<td></td>
<td style="text-align:right;"><button class="k-button" id="login" onclick="Login()">Login</button></td>
</tr>
</tbody>
</table>
</div>
</div>
<script type="text/javascript">
function Login() {
$.ajax({
url: '#Url.Content("~/Login/LoginAccess")',
type: 'POST'
});
}
Home Controller..
public ActionResult Index()
{
Session["UserName"] = "Administrator";
string menu = this.GetMenu();
ViewBag.ManueItems = menu;
return View("User");
}
After click on the login button it comes to LoginAccess in Login controller and then comes to Home controller Index method, but doesn't view the "user view".
But when i check with typing url >>(host__/Login/LoginAccess">http://__host__/Login/LoginAccess) Its working properly.
Please help me to slove this problem.
Thank you.. :)

You may misuse the Ajax function here
You should use #Html.ActionLink("Login", "LoginAccess", "Login") instead
Ajax is originally used to get something from server side other than affecting currently browsing page.

When you are doing Ajax calls, you cannot force redirect from controller. You can fix this by 2 ways:
Replace ajax call with regular get.
Return a json from the action and use redirect from javascript

try this instead
return redirect("/Home/Index")

You can try this
var result = new ControllerName().YourAction();

Related

How to pass checkbox values to the controller in Spring MVC

I have a jsp page with list of functions. Here in controller I get this list from database and pass it to jsp.
#RequestMapping(value = "/functionlist", method = RequestMethod.GET)
public ModelAndView functionList(Model model) throws Exception {
ModelAndView mv = new ModelAndView("functionList");
mv.addObject("functionList", getFunctionsFromDB());
return mv;
}
In my jsp page I create table using this list of functions
<table id="table">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<c:choose>
<c:when test="${not empty functionList}">
<c:forEach var="function" items="${functionList}">
<tr>
<td><input name="id" value="${function.id}" hidden></td>
<td>${function.name}</td>
<td>
<input type="checkbox" id="${function.id}" value="${function.action}"></td>
</tr>
</c:forEach>
</c:when>
</c:choose>
</tbody>
</table>
<button type="submit" name="save">Save</button>
I also give function id to checkbox id.
My Function entity is the following
public class Function {
private Integer id;
private String name;
private Boolean action;
...
}
I want to press button Save and get in controller "/functionlist/save" my list of checkbox values.
Try to add form like this to your jsp page
<form:form id="yourForm" action="/functionlist/save" method="POST" modelAttribute="functionList">
<c:forEach items="${functionList}" varStatus="status" var="function">
<tr>
<td>${function.name}</td>
<td>
<form:checkbox path="functionList[${status.index}].action"/>
</td>
</tr>
</c:forEach>
<input type="submit" value="submit" />
</form:form>
and in Controller you should have a method like this
#RequestMapping(value = { "/functionlist/save" }, method = RequestMethod.POST)
public String savePerson(#ModelAttribute("functionList")List<Function> functionList) {
// process your list
}
If this does not work, you can try to wrap you list.
public class FunctionListWrapper {
private List<Function> functionList;
public FunctionListWrapper() {
this.functionList = new ArrayList<Function>();
}
public List<Function> getFunctionList() {
return functionList;
}
public void setFunctionList(List<Function> functionList) {
this.functionList = functionList;
}
public void add(Function function) {
this.functionList.add(function);
}
}
in controller instead of passing list, pass wrapper
FunctionListWrapper functionListWrapper=new FunctionListWrapper();
functionListWrapper.setFunctionList(userService.getFunctionList());
mv.addObject("functionListWrapper", functionListWrapper);
For more details please take a look at this questions: question 1 and question 2
First you need to add name attribute to your checkbox inputs.You can get these in
an array on controller with same name as your name attribute.eg-
#RequestMapping(value = "/functionlist", method = RequestMethod.GET)
public ModelAndView functionList(Model model,#RequestParam("checkboxname")String[] checkboxvalues) throws Exception {
ModelAndView mv = new ModelAndView("functionList");
mv.addObject("functionList", getFunctionsFromDB());
return mv;
}
few things.
First you should think about a form object, which is the exchange entity between the view and the controller. The form entity will be something similar to the followng:
public class Form {
private List<Function> functions;
//getters & setters
}
secondly, since you are using Spring MVC, you should leverage the <%# taglib uri="http://www.springframework.org/tags/form" prefix="form" %> library. Consequently, your form will be:
<form:form commandName="form" action="/your/url">
<c:forEach items="${form.functions }" var="function" varStatus="status">
<tr>
<td><form:hidden path="functions[${status.index }].id"></td>
<td>${function.name}</td>
<td>
<form:checkbox path="functions[${status.index }].action" id="${function.id}" value="${function.action}"/>
</td>
</tr>
</c:forEach>
</form:form>
and finally the controller will be something like
#RequestMapping(value="/your/url", method=RequestMethod.POST)
public String postForm(#ModelAttribute("form") FormForm form)
{
//cool stuff here
}
please note that the proper HTTP method is POST, not GET. Yup, I know things work also with GET it's definitely a deprecated strategy.
In addition, figure out how I referred the list of Function in the Form. I used the variable function in the foreach statement when I had to display data, I referred the list when I had to bind the Form object for transferring data to the controller. Last but not least, I haven't tried the code. I wrote it on the fly just to give you hints about how to do it properly.
One last thing. Since you pass the Form to the JSP, you don't need anymore to fill the Model with the attribute you used. Just fill the form with your data and use it to diaplay them in the view. Just like this ${form.stuff.you.want}

Spring MVC 3.2 Thymeleaf Ajax Fragments

I'm building application with Spring MVC 3.2 and Thymeleaf templating engine. I'm a beginner in Thymeleaf.
I have everything working, including Thymeleaf but I was wondering if anyone knows of a simple and clear toturial on how to do simple Ajax request to controller and in result rendering only a part of a template (fragment).
My app has everything configured (Spring 3.2, spring-security, thymeleaf, ...) and works as expected. Now I would like to do Ajax request (pretty simple with jQuery but I don't wan't to use is since Thymeleaf in its tutorial, chapter 11: Rendering Template Fragments (link) mentiones it can be done with fragments.
Currently I have in my Controller
#RequestMapping("/dimensionMenuList")
public String showDimensionMenuList(Model model) {
Collection<ArticleDimensionVO> articleDimensions;
try {
articleDimensions = articleService.getArticleDimension(ArticleTypeVO.ARTICLE_TYPE);
} catch (DataAccessException e) {
// TODO: return ERROR
throw new RuntimeException();
}
model.addAttribute("dimensions", articleDimensions);
return "/admin/index :: dimensionMenuList";
}
the part of the view where I would like to replace <ul></ul> menu items:
<ul th:fragment="dimensionMenuList" class="dropdown-menu">
<li th:unless="${#lists.isEmpty(dimensions)}" th:each="dimension : ${dimensions}">
</li>
</ul>
Any clue is greatly appreciated. Especially if I don't have to include any more frameworks. It's already too much for java web app as it is.
Here is an approach I came across in a blog post:
I didn't want to use those frameworks so in this section I'm using jQuery to send an AJAX request to the server, wait for the response and partially update the view (fragment rendering).
The Form
<form>
<span class="subtitle">Guest list form</span>
<div class="listBlock">
<div class="search-block">
<input type="text" id="searchSurname" name="searchSurname"/>
<br />
<label for="searchSurname" th:text="#{search.label}">Search label:</label>
<button id="searchButton" name="searchButton" onclick="retrieveGuests()" type="button"
th:text="#{search.button}">Search button</button>
</div>
<!-- Results block -->
<div id="resultsBlock">
</div>
</div>
</form>
This form contains an input text with a search string (searchSurname) that will be sent to the server. There's also a region (resultsBlock div) which will be updated with the response received from the server.
When the user clicks the button, the retrieveGuests() function will be invoked.
function retrieveGuests() {
var url = '/th-spring-integration/spring/guests';
if ($('#searchSurname').val() != '') {
url = url + '/' + $('#searchSurname').val();
}
$("#resultsBlock").load(url);
}
The jQuery load function makes a request to the server at the specified url and places the returned HTML into the specified element (resultsBlock div).
If the user enters a search string, it will search for all guests with the specified surname. Otherwise, it will return the complete guest list. These two requests will reach the following controller request mappings:
#RequestMapping(value = "/guests/{surname}", method = RequestMethod.GET)
public String showGuestList(Model model, #PathVariable("surname") String surname) {
model.addAttribute("guests", hotelService.getGuestsList(surname));
return "results :: resultsList";
}
#RequestMapping(value = "/guests", method = RequestMethod.GET)
public String showGuestList(Model model) {
model.addAttribute("guests", hotelService.getGuestsList());
return "results :: resultsList";
}
Since Spring is integrated with Thymeleaf, it will now be able to return fragments of HTML. In the above example, the return string "results :: resultsList" is referring to a fragment named resultsList which is located in the results page. Let's take a look at this results page:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
</head>
<body>
<div th:fragment="resultsList" th:unless="${#lists.isEmpty(guests)}" id="results-block">
<table>
<thead>
<tr>
<th th:text="#{results.guest.id}">Id</th>
<th th:text="#{results.guest.surname}">Surname</th>
<th th:text="#{results.guest.name}">Name</th>
<th th:text="#{results.guest.country}">Country</th>
</tr>
</thead>
<tbody>
<tr th:each="guest : ${guests}">
<td th:text="${guest.id}">id</td>
<td th:text="${guest.surname}">surname</td>
<td th:text="${guest.name}">name</td>
<td th:text="${guest.country}">country</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
The fragment, which is a table with registered guests, will be inserted in the results block.
Rendering only Thymeleaf fragments also works well with ModelAndView.
Your controller
#RequestMapping(value = "/feeds", method = RequestMethod.GET)
public ModelAndView getFeeds() {
LOGGER.debug("Feeds method called..");
return new ModelAndView("feeds :: resultsList");
}
Your view
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head></head>
<body>
<div th:fragment="resultsList" id="results-block">
<div>A test fragment</div>
<div>A test fragment</div>
</div>
</body>
</html>
What's actually rendered
<div id="results-block">
<div>A test fragment</div>
<div>A test fragment
</div>
</div>
As an alternate version to Sohail's great answer, I want to give a version that using javascript can send the whole th:object to the controller, integrating Thymeleaf in your forms, not having to use #PathVariable which becomes messy or not usable at all when you've forms with many fields.
For the form (using an example which returns an object which has an id and a name Strings, and feeds a combobox with a Map that has some of those objects as values) we have:
<form method="post" th:action="#{/yourMapping}" th:object="${object}" id="yourFormId">
<select th:field="*{mapOfObjects}">
<option
th:each="entry: ${mapOfObjects}"
th:value="${entry.value.id}"
th:text="${entry.value.name}" >
</option>
</select>
<p>Name:
<input type="text" th:field="*{name}" />
</p>
</form>
When this form is submited (using a button with type submit for example) the whole document will be replaced. However we can intercept this submit with javascript and do it the ajax-way. To achieve this, we will add an interceptor to our form using a function. First call the function that adds the interceptor right after the form:
<script>formInterceptor("yourFormId");</script>
And the function looks like this (place it in the head of the document or wherever suits your needs):
<script>
function formInterceptor(formName) {
var $form = $("#" + formName);
$form.on('submit', function(e) {
e.preventDefault();
$.ajax({
url : $form.attr('action'),
type : 'post',
data : $form.serialize(),
success : function(response) {
if ($(response).find('.has-error').length) {
$form.replaceWith(response);
}
else{
$("#ajaxLoadedContent").replaceWith(response);
}
}
});
});
};
</script>
Now whenever the form is submited, this function will trigger, and it will:
Prevent the original form submit
Make an ajax call using the url defined in the form's th:action
Serialize the form data. Your controller will be able to recieve this in an object
Replace the part of your html code with the returned fragment
The replaced part should look like this
<div id="ajaxLoadedContent"></div>
And the controller can recieve the th:object in the form, with it's values filled, like this (Replace Object with your object's type and "object" with a proper name):
#PostMapping(value = /yourMapping)
public String ajaxCtrlExample(#ModelAttribute("object") Object object, Model model) {
return yourFragmentPath;
}
And that's everything. Call the function that adds the interceptor after every form you need in ajax-version.

display model contents dynamically in View MVC4

I have a homepage that will display a table with some data for each user. The back-end handles that and I have a list in my model. I am trying to view a dynamic table based on this list and be able to delete elements from without having to hit refresh. I do not know where to start to do something like this. Any help?
Here is what I have so far:
Inside HomePage controller I have an action returning Json representation of the model. Have of 'HpModel' gets set in the login controller and the other is in this one:
public JsonResult GetUserInfo(HomePageModel HpModel)
{
DBOps ops = new DBOps();
HpModel.PhoneDisplay = ops.getDisplayInfo(HpModel.ExtNum);
HpModel.NumberOfLines = HpModel.PhoneDisplay.Count;
return Json(HpModel);
}
In my view I have a javascript to grab this model:
function getInfo() {
alert('here');
$.ajax({
url: '#Url.Action("GetUserInfo", "HomePage")',
data: json,
type: 'POST',
success: function (data) {
alert(data);
}
});
}
I am not sure what is going wrong, and not 100% sure its the way to be done anyway.
Help is appreciated :)
One more idea. You may use jQuery to hide and callback function to $Post to your Delete ActionResult.
For examp: (here I created easy example without $post: jsfiddle)
<script>
$('.delete').click(function()
{
$(this).closest('tr').hide(callback);
function callback() {
$post(/Home/Delete/....
});
</script>
<table>
<tr>
<td>Marry</td>
<td>10 points</td>
<td><a class="delete" href="#">Delete</a></td>
</tr>
<tr>
<td>Jane</td>
<td>8 points</td>
<td><a class="delete" href="#">Delete</a></td>
</tr>
<tr>
<td>Lara</td>
<td>5 points</td>
<td><a class="delete" href="#">Delete</a></td>
</tr>
</table>

How to POST to database through URL

I'm writing a web application in Spring/Hibernate that handles basic voting functionality. I want to have a link to /vote/{gameId} which will add that vote to the database for that specific ID. I'm really at a loss as for how to accomplish this though. Here's what I've tried in my controller:
#RequestMapping(value="/vote/{gameId}", method = RequestMethod.POST)
public String addVote(#PathVariable("gameId")
Integer gameId) {
Vote vote = new Vote();
vote.setGameId(gameId);
voteService.addVote(vote);
return "redirect:/games/wanted.html";
}
Here's where the link shows up in a jsp:
<c:if test="${!empty games}">
<table>
<tr>
<th>Game Title</th>
<th>Votes</th>
<th> </th>
</tr>
<c:forEach items="${games}" var="game">
<tr>
<td><c:out value="${game.title}"/></td>
<td>Placeholder</td>
<td>Vote!</td>
</tr>
</c:forEach>
</table>
</c:if>
When I try this though I just get a 404 error. Any insight would be great.
This is how you make a post call with plain Javascript:
var url = "vote";
var params = "id=1";
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(params);
You need to call this in the onclick of your link.
On the other hand it is a lot easier if, for example, you use the jQuery Javascript library:
For your particular case it would be something like:
$.post("vote", { id: "1" } );
Or the full jQuery answer (remember to replace #linkid with the id of you tag):
$(document).ready(function() { //this runs on page load
// Handler for .ready() called.
$('#linkid').click(function(event) { //this finds your <a> and sets the onclick, you can also search by css class by type of tag
$.post("vote", { id: "1" } );
return false; //this is important so that the link is not followed
});
});

Partial view in MVC3 Razor view Engine

I have an view in MVC3 Razor view engine like following image. Now i want to Confirm Connection Action Output show under this link text not New page. How can i done this work?
Please explain with example code.
My View Like this :
#model ESimSol.BusinessObjects.COA_ChartsOfAccount
#{
ViewBag.Title = "Dynamic Account Head Configure";
}
<h2>Dynamic Account Head Configure</h2>
<table border="0">
<tr>
<td> Select an Server Connection </td>
<td style="width:5px">:</td>
<td>#Html.DropDownListFor(m => m.DBConnections, Model.DBConnections.Select(x => new SelectListItem() { Text = x.ConnectionName, Value = x.DBConnectionID.ToString()}))</td>
</tr>
<tr>
<td> </td>
<td style="width:5px"></td>
<td>#Html.ActionLink("Confirm Connection", "ConformConnection")</td>
</tr>
</table>
AND My Controller action Like following :
public ActionResult ConfirmConnection()
{
return PartialView();
}
I'm a big fan of using jquery and ajax for this kind of thing ...
http://api.jquery.com/jQuery.ajax/
If you are following the typical MVC model then you can add an action link to the page using something like ...
#Html.ActionLink("controller", "action", args);
but I would go for the ajax driven approach ...
<script type="text/javascript">
var ajaxBaseUrl = '#Url.Action("yourController", "ConformConnection", new { args })';
$(link).click(function () {
var currentElement = $(this);
$.ajax({
url: ajaxBaseUrl,
data: { any other queryString stuff u want to pass },
type: 'POST',
success: function (data) {
// action to take when the ajax call comes back
}
});
});
});
</script>
First move your markup to a partial view. After that define an action method that renders your partial view.
[ChildActionOnly]
public ActionResult ConfirmConnection(COA_ChartsOfAccount model)
{
return PartialView("MyPartialView", model);
}
ChildActionOnly attribute makes sure this action method cannot be called by a HTTP request.
Then you can display it whenever you want using Html.Action method.
#Html.Action("ConfirmConnection", "MyController", new { model = Model })
Ignore passing the model as a parameter if it doesn't change by the page you display it. You can retrieve it in your action method.

Resources