Here is my problem:
Inside a jQuery dialog I have the following code:
<%:Ajax.ActionLink("Yes", "SendClaim", "Claim", new { id = Model.ExpenseId }, new AjaxOptions { UpdateTargetId = "dialog" }, new { #class = "button" })%>
When stuff fails in the controller based on roles I return a partial view that replaces the existing dialog (see UpdateTargetId = "dialog").
When everything works I want to do a redirect to another page (an index of all claims) to stop the user performing additional actions but this entire page is rendered inside the jQuery dialog due to it being an ajax request with an update id.
What is the correct way to approach the problem?
I'm a bit of a novice, but I find I have more control with the following approach instead of using Ajax.ActionLink. Hopefully it helps and I have understood what you want to do correctly.
Claim Controller:
[AcceptVerbs(HttpVerbs.Post)]
public Json Send(int expenseId)
{
// Check user stuff
if(valid)
// do stuff
return new Json(true, JsonRequestBehavior.AllowGet);
else
return new Json(false, JsonRequestBehavior.AllowGet);
}
jQuery
function submitClaim() {
$.ajax({
url: "/Claim/Send",
type: "POST",
dataType: "json",
data: { 'expenseId': <%=Model.ExpenseId> },
success: function (data) {
if(data) { // if successful, redirect
document.location = "Claim/Index";
}
else { //load your partial view into your dialog
$("#idOfYourDialog").load('Claim/Error/');
}
},
error: function (xhr) { }
});
}
html
Submit
Returned an 'All OK' dialog and had the following javascript when the user clicks the ok button:
function redirect() {
document.location = "<%:(String)ViewBag.Redirect %>";
}
$(document).ready(function() {
$(".ui-dialog-titlebar-close").click(function() {
redirect();
});
});
Seems unavoidable - you can't seem to do an RedirectToAction when the controller action has been called from Ajax.ActionLink as the response will be stuck into the updatetargetid.
Related
I have a method which return an action to a different controller. I am using return RedirectToAction and passing a parameter with it. The parameter successfully passed to the other controller. But it does not return any view. The page should load and return a new view. Here is my code:
Controller 1:
public ActionResult Work(int id, int staffId)
{
return RedirectToAction("CreateStaffWork", "Staff", new { id = staffId});
}
Controller 2 (Staff):
public ActionResult CreateStaffWork(int id)
{
Staff staffInfo= db.Staff.Find(id);
StaffInputModel newStaffWork = new StaffInputModel { StaffId = staffInfo.Id };
return View(newStaffWork);
}
It should return CreateStaffWork view, but the page does not reload. There is no error while running the code. What should I do for the view to return?
I submit the form using ajax request:
<script type="text/javascript">
$(document).ready(function () {
$("#LoadStaffListTable tbody").on('click', '.select', function (e) {
e.preventDefault();
$.ajax({
url: '/StaffWork/Work',
type: 'POST',
data: { id: $(this).data('id'), staffId: $(this).data('staffId') },
dataType: 'json',
}); // end ajax
});
});
As mentioned in the comments, the purpose of ajax is to stay in the same page. If you're redirecting to a new page, you simply redirect to the Work action methods with proper parameters.
Change your click event handler to:
$("#LoadStaffListTable tbody").on('click', '.select', function(e) {
location.href = '#Url.Action("Work", "StaffWork")?id=' + $(this).data('id') + '&staffId=' + $(this).data('staffId');
});
I have a view (Index.cshtml) with a grid (Infragistics JQuery grid) with an imagelink. If a user clicks on this link the following jquery function will be called:
function ConfirmSettingEnddateRemarkToYesterday(remarkID) {
//Some code...
//Call to action.
$.post("Home/SetEnddateRemarkToYesterday", { remarkID: remarkID }, function (result) {
//alert('Succes: ' + remarkID);
//window.location.reload();
//$('#remarksgrid').html(result);
});
}
Commented out you can see an alert for myself and 2 attempts to refresh the view. The location.reload() works, but is basically too much work for the browser. The .html(result) posts the entire index.cshtml + Layout.cshtml double in the remarksgrid div. So that is not correct.
This is the action it calls (SetEnddateRemarkToYesterday):
public ActionResult SetEnddateRemarkToYesterday(int remarkID) {
//Some logic to persist the change to DB.
return RedirectToAction("Index");
}
This is the action it redirects to:
[HttpGet]
public ActionResult Index() {
//Some code to retrieve updated remarks.
//Remarks is pseudo for List<Of Remark>
return View(Remarks);
}
If I don't do window.location.reload after the succesfull AJAX post the view will never reload. I'm new to MVC, but i'm sure there's a better way to do this. I'm not understanding something fundamental here. Perhaps a nudge in the right direction? Thank you in advance.
As you requesting AJAX call, you should redirect using its response
Modify your controller to return JSONResult with landing url:
public ActionResult SetEnddateRemarkToYesterday(int remarkID) {
//Some logic to persist the change to DB.
var redirectUrl = new UrlHelper(Request.RequestContext).Action("Index", "Controller");
return Json(new { Url = redirectUrl });
}
JS Call:
$.post("Home/SetEnddateRemarkToYesterday", { remarkID: remarkID }, function (result) {
window.location.href = result.Url
});
After Ajax post you need to call to specific Url..
like this..
window.location.href = Url
When using jQuery.post the new page is returned via the .done method
jQuery
jQuery.post("Controller/Action", { d1: "test", d2: "test" })
.done(function (data) {
jQuery('#reload').html(data);
});
HTML
<body id="reload">
For me this works. First, I created id="reload" in my form and then using the solution provided by Colin and using Ajax sent data to controller and refreshed my form.
That looks my controller:
[Authorize(Roles = "User")]
[HttpGet]
public IActionResult Action()
{
var model = _service.Get()...;
return View(model);
}
[Authorize(Roles = "User")]
[HttpPost]
public IActionResult Action(object someData)
{
var model = _service.Get()...;
return View(model);
}
View:
<form id="reload" asp-action="Action" asp-controller="Controller" method="post">
.
.
.
</form>
Javascript function and inside this function I added this block:
$.ajax({
url: "/Controller/Action",
type: 'POST',
data: {
__RequestVerificationToken: token, // if you are using identity User
someData: someData
},
success: function (data) {
console.log("Success")
console.log(data);
var parser = new DOMParser();
var htmlDoc = parser.parseFromString(data, 'text/html'); // parse result (type string format HTML)
console.log(htmlDoc);
var form = htmlDoc.getElementById('reload'); // get my form to refresh
console.log(form);
jQuery('#reload').html(form); // refresh form
},
error: function (error) {
console.log("error is " + error);
}
});
No i have been stuck here ... can you please help me out...
$(':submit').click(function (e) {
var username = $('#username').val();
var password = $('#password').val();
var postdata =
{
'Email': username,
'Password': password
};
$.post({
url: 'http://localhost:7651/Home/CheckLogin',
data: postdata,
success: function (msg) {
alert('Hi');
}
});
});
this is not working ...its not calling the action controller somehow...
my controller action is
public string CheckLogin(Users checkuser)
{
if (db.CheckUserLoginDetails(checkuser.Email, checkuser.Password))
{
return "Login Successful:" + checkuser.Email;
}
else
{
return "Login UnSuccessful";
}
}
please help.... also do i need to prevent the defualt behavior of the submit button like e.preventDefault();
Here are the steps you need to do:
Your LoginController would need to validate the login and return the HTML Fragments containing the Login Status. Note that you don't need a fullblown HTML here. Just the fragments containing the result
As you probably know, you can utilize jQuery.ajax that you put in your view. To append the Login Result into the DIV, you could use jQuery.html Here is the snippet that you would need (NOTE: not debugged yet, but roughly something like below)
// Override form submit
$("form").live("submit", function (event) {
event.preventDefault();
var form = $(this);
$.ajax({
// Get the action URL
url: form.attr('action'),
type: "POST",
// get all form variables
data: form.serialize(),
// upon success, the fragment of HTML from the Controller will be stored in loginResultHtml
success: function(loginResultHtml){
// append the html to your login DIV id using jQuery.html function
$(#your-login-status-div-id).html(loginResultHtml);
}
});
});
Is there any convenient way to integrate ASP.NET MVC validation (I am primarily interested in Fluent Validation) with forms submitting by Ajax?
The easiest way to achieve this is to place those forms inside partials and then submit them using AJAX. The controller action which will handle the POST will check if the model is valid and if not return the partial in order to show the validation errors. For example:
<div id="myform_container">
<!-- The _Foo partial will contain a form -->
#Html.Partial("_Foo")
</div>
and a controller action which will handle the submission:
[HttpPost]
public ActionResult Foo(SomeViewModel model)
{
if (!ModelState.IsValid)
{
return PartialView("_Foo", model);
}
// TODO: process the results and inform the user that everything went fine:
return Json(new { success = true });
}
Now all that's left is to AJAXify this form in a separate javascript file:
$(function() {
// Use delegate to preserve the .submit handler when we refresh the container
$('#myform_container').delegate('form', 'submit', function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
if (result.success) {
// the server returned JSON
alert('thanks for submitting');
} else {
// the server returned the partial => update the DOM
$('#myform_container').html(result);
}
}
});
return false;
});
});
I have a Html.Helper that I use to delete rows from my grid.
It calls the following method on my controller;
[AcceptVerbs(HttpVerbs.Delete)]
public ActionResult Delete(int _employeeOtherLeaveId)
{
EmployeeOtherLeaf.Delete(_employeeOtherLeaveId);
return RedirectToAction("Payroll");
}
This calls the GET method on my controller which I would expect to refresh the view of my grid, but it doesn't. When I manually refresh I see the row has in fact been deleted. Why is this?
[HttpGet]
public ActionResult Payroll()
{
if ((SessionObjects.PeriodStartDate > DateTime.MinValue) && (SessionObjects.PeriodEndDate > DateTime.MinValue))
if (SessionObjects.PayrollSelectedEmployeeId == 0)
return View(new PayrollViewModel()
{
PeriodStartDate = SessionObjects.PeriodStartDate,
PeriodEndDate = SessionObjects.PeriodEndDate
});
else
return View(new PayrollViewModel(
SessionObjects.PeriodStartDate,
SessionObjects.PeriodEndDate,
SessionObjects.PayrollSelectedEmployeeId
));
return View();
}
This will depend how you are calling the DELETE action. Judging from your previous question and the answer you accepted I suppose that you are doing the following:
onclick="$.ajax({url: this.href, type: 'DELETE'}); return false;"
which obviously is insufficient as you are sending the AJAX request to delete but you aren't handling the success event to update the DOM. So you might need to do this:
$.ajax({
url: this.href,
type: 'DELETE',
success: function(result) {
// update some DOM element with the result returned by the
// server. So supposing that you have some <div id="someContainer">
// that will contain the part of the DOM you want updated:
$('#someContainer').html(result);
}
});
return false;
Now obviously stuffing all this javascript inside the HTML as you were using your custom helper is ugly. Personally I would use unobtrusive javascript. I would have my helper generate a normal anchor with a class and then in a completely separate javascript file I would AJAXify this link:
$(function() {
// AJAXify the anchor with the delete class that would
// be generated by your custom helper
$('.delete').click(function() {
$.ajax({
url: this.href,
type: 'DELETE',
success: function(result) {
// update some DOM element with the result returned by the
// server. So supposing that you have some <div id="someContainer">
// that will contain the part of the DOM you want updated:
$('#someContainer').html(result);
}
});
return false;
});
});