I have the following code. When I subit via Ajax, I can see the call go to the controller, and it returns the correct results. However, although it returns success, the partial is not being updated. Its almost certainly something stupid I am doing, but I have been starting at this so long now that Im going round in circles.
My suspicion is that I need to handle JSON data differently if I want to display it as a set of models in a partial. But as I am still finding my feet with MVC and ajax, its a lot of trial and error at present.
#{
System.Web.Mvc.Ajax.AjaxOptions ajaxopts = new AjaxOptions()
{
HttpMethod = "Post",
UpdateTargetId = "dlrsTable",
OnBegin = "OnBegin",
OnComplete = "OnComplete",
OnSuccess = "OnSuccess",
OnFailure = "OnFailure"
};
}
#using (Ajax.BeginForm("RefreshGrid", "Dealership", ajaxopts, new { id = "allDlrs" }))
{
#Html.Hidden("showArchived", false )
#Html.Hidden("ShowPage", 0)
#Html.AntiForgeryToken()
<div id="dlrTable">
#{Html.RenderPartial("_allDealerships", Model);}
</div>
}
and my controller;
public async Task<JsonResult> RefreshGrid(bool? showArchived, int? ShowPage)
{
try
{
//code elided, I can see it works and mappedDlrs contains the new data I want
return new JsonResult(){ Data = mappedDlrs };
}
catch (Exception ex)
{
_log.Error(ex, string.Format("Error in DealershipController.AllDealerships - Session {0}", Session.SessionID));
return new JsonResult() { Data = "Error curred" };
}
}
Your update target and div IDs do not match.
UpdateTargetId = "dlrsTable"
<div id="dlrTable">
Note the missing s in the div id (or extra one in the UpdateTargetId)
Related
I have a view which when a teacher is logged in lists the complete details of a student , it also lists the tasks given to the student by the teacher logged in. If the teacher wants to create a new task for the student he clicks the create new link which in turns make an Ajax call to the controller:
#Ajax.ActionLink("Create", "CreateTask", "Task", new { id = Model.StudentId },
new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "create-div"
}, new { #class = "btn btn-default" })
which returns a partial view
[HttpGet]
public ActionResult CreateTask(int ?id)
{
//........
return PartialView("PartialViews/Task/_CreateTaskPartial");
}
In the partial view I am using Ajax.BeginForm to submit the data to create the actual task as follows
#using (Ajax.BeginForm("CreateTask", "Task",new AjaxOptions { UpdateTargetId = "create-div", InsertionMode = InsertionMode.Replace }))
{
// Form data
}
and finally in the CreateTask controller I create the task
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include="TaskId")] Task #task)
{
if (ModelState.IsValid)
{
db.Tasks.Add(#task);
db.SaveChanges();
// If everything is successfull return empty
return new EmptyResult();
}
// If model errors send the view back
return PartialView("PartialViews/Task/_CreateTaskPartial", #task);
}
It creates the new task successfully but it does not update the main view which lists the details of a student and a list of created tasks. I have to refresh the page to see the last task added.
How can I make it possible so that when a 6th task is added via partial view, on success it updates the parent view and lists the 6th task also ?
I am not very experienced in MVC so please correct me where am I doing wrong.
I solved it, I got help from Here to solve it.
So what I did is instead of returning an EmptyResult() when the task is created I returned a JSON object
if (ModelState.IsValid)
{
db.Tasks.Add(#task);
db.SaveChanges();
// If everything is successfull return empty
//return new EmptyResult();
return Json(new { ok = true, url = Url.Action("Details","Student",new{id=#event.StudentId}) });
}
An d in the partial view which submits the form to vreate the task I added OnSuccess parameter in the AjaxOptions in the Ajax.BeginForm which calls a javascript function.
#using (Ajax.BeginForm("CreateTask", "Task",new AjaxOptions { UpdateTargetId = "create-div", InsertionMode = InsertionMode.Replace,OnSuccess = "onSuccess" }))
{
// Form data
}
And finally in the "onSuccess" function I cheked if the result is ok then redirect to the url in the result given by the controller.
var onSuccess = function doIt(result) {
if (result.ok) {
window.location.href = result.url;
}
};
I have the following Ajax.actionlink which will the action method and return a JSON:-
#Ajax.ActionLink("Start Process", "StartProcess", "Home",
new { name = "BuisnessProcess" },
new AjaxOptions
{ HttpMethod = "POST",
LoadingElementId = "tobehide2",
UpdateTargetId = "startprocess",
OnSuccess = "Animate" })
</div> <img id="tobehide2" src="~/Content/ajax-loading2.gif" />
Currently when the user clicks on the link it will display the JSON info in the browser:-
{"activityId":"2119_666_BuisnessProcess_process1_setverialbe","processId":"666_BuisnessProcess_process1"}
But what i trying to do is to build another Ajax.actionlink based on the returned Json and pass the activityId as a new parameter to the Ajax.actionlink.
Best Regards
:::UPDATED:::
[HttpPost]
public ActionResult StartProcess(string name)
{
using (var client = new WebClient())
{
try
{
var query = HttpUtility.ParseQueryString(string.Empty);
query["j_username"] = "kermit";
query["hash"] = "9449B5ABCFA9AFDA36B801351ED3DF66";
query["loginAs"] = User.Identity.Name;
query["imagurl"] = "123";
var url = new UriBuilder("http://localhost:8080/jw/web/json/workflow/process/start/" + name.ToString() + ":28:process1");
url.Query = query.ToString();
string json = client.DownloadString(url.ToString());
Thread.Sleep(500);
return Content("Process started succsfully. Returned values are :-" + json);
}
catch (System.Net.WebException ex)
{
return Content("", "application/json");
}
}
}
when you return data in action, to combine html string.
test
to UpdataTargetId : startprocess.
when you return the json to view, then execute "Animate" function.
so, you can construct the link in Animate.
function Animate(result)
{
$(result).each(function(index, item){
// todo construct the link
});
}
I want to call "OnFailure" when ModelState is not valid in controller.
In My LoginView
#using (Ajax.BeginForm("Login", new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "Login",InsertionMode = InsertionMode.Replace, OnSuccess = "Success", OnFailure = "onError" }))
{
}
In Controller
[httpPost]
public ViewResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
}
else
{
ModelState.AddModelError("login is fail")
}
return View("Login",model)
}
so i want call onSuccess Method if ModelState is valid and if it fail then call only OnError method with display all error which are in Model State.
Here's what you could do:
[HttpPost]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
// everything went fine and we want to redirect in this case =>
// we pass the url we want to redirect to as a JSON object:
return Json(new { redirectTo = Url.Action("SomeController", "SomeAction") });
}
else
{
// there was an error => add an error message
ModelState.AddModelError("login is fail")
}
// return a partial view instead of a full vire
return PartialView("Login",model)
}
and then all you need is the Success function:
#using (Ajax.BeginForm("Login", new AjaxOptions { HttpMethod = "POST", OnSuccess = "loginAjaxSuccess" }))
{
}
in which you could test in which case you are:
function loginAjaxSuccess(result) {
if (result.redirectTo) {
// the controller action returned a JSON result => it was a successful login
// => we redirect the browser to this url
window.location.href = result.redirectTo;
} else {
// the action returned a partial view with the form containing the errors
// => we need to update the DOM:
$('#Login').html(result);
}
}
By the way if you are using unobtrusive client side validation in the case of error where you are refreshing the form you will need to manually force the parsing of the new validation rules, otherwise next time you attempt to submit the form, client validation won't work:
} else {
// the action returned a partial view with the form containing the errors
// => we need to update the DOM
$('#Login').html(result);
// Now that the DOM is updated let's refresh the unobtrusive validation rules on the form:
$('form').removeData('validator');
$('form').removeData('unobtrusiveValidation');
$.validator.unobtrusive.parse('form');
}
When you detect the problem in the ModelState, set the StatusCode of the response object to something like 400 (You can get the code from the System.Net.HttpStatusCode class)
That will fire the onfailure method.
Si
I'm trying to make request returns on ajax updated partial view. Apparently request is not returned from the ajax-function.
Here ajax-code:
<script type="text/javascript">
function doAjaxPost(myid) {
// get the form values
var ApplSort = $('#DropDownListSort').val();
var radio_check_val=0;
for (i = 0; i < document.getElementsByName('radio').length; i++) {
if (document.getElementsByName('radio')[i].checked) {
radio_check_val = document.getElementsByName('radio')[i].value;
}
}
// alert("myid=" + myid +";"+ "ApplSort=" + ApplSort + ";" + "radio_check_val=" + radio_check_val);
$.ajax(
{
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: { ApplSort: ApplSort, radio_check_val: radio_check_val, myid: myid },
UpdateTargetId: "tabledata",
dataType: 'html',
url: 'Partner/PartnerApplications',
success: function (data) {
var result = data;
$('tabledata').html(result);
},
error: function (error) {
alert('Ошибка AJAX-запроса. Обновите страницу!');
}
});
}
</script>
Fail is called and the page is completely updated.
Here's updated content in the view:
<div id="target">
#Html.Partial("~/Views/Partner/PartnerApplicationsPartial.cshtml")
</div>
controller's code:
[HttpPost]
public ActionResult PartnerApplications(int[] ApplSort, int[] radio_check_val, int[] myid)
{
MordaPartner MrdPrt = new MordaPartner(Server, Request);
if (Request.IsAjaxRequest())
{
var obj = MrdPrt.morda_obj.CookieAuthenticationPartner(Server, Request, Response, MrdPrt.PartnerLogin, MrdPrt.PartnerPassword);
if (obj != null)
{
//alert("ApplSort=" + ApplSort + ";" + "ApplSelectOffer=" + ApplSelectOffer + ";" + "ApplSelectAuction=" + ApplSelectAuction + ";" + "ApplSelectNoOffer=" + ApplSelectNoOffer);
var objs = from s in MrdPrt.morda_obj.entities.applications where s.application_user_city == obj.partner_city & s.application_blocked != 1 orderby s.application_id ascending select s;
return Json(new { data = this.RenderPartialViewToString("PartnerApplicationsPartial", objs) });
}
else
{
return RedirectToAction("Registration");
}
}
else { return RedirectToAction("PartnerApplications"); }
}
RenderPartialViewToString it was taken from here: http://www.c-sharpcorner.com/blogs/7150/implementing-renderpartialviewtostring-in-asp-net-mvc-3.aspx
script is loaded:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
What am I doing wrong?
I think your easiest solution since you are just wanting to do a partial...
#using( Ajax.BeginForm( "PartnerApplications",
null,
new AjaxOptions() {
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "target",
LoadingElementId = "AjaxSearch" },
new { id = "UserSearchForm" } ) ) {
<input type="text" id="id" name="id" placeholder="Enter Search" />
}
This is an ability that is built into MVC that makes it VERY easy to update an element with the results of a partial.
All this is saying is that you want a new Ajax Form that calls the PartnerApplications Action. You want the action called with an HttpMethod that is a POST request and you want the results to replace (InsertionMode.Replace) the existing elements in the target (whatever that may be) and while the request is taking place you want the element AjaxSearch visible (this is optional, but something I use to show that it's working).
This will generate the required JavaScript for you and until you get into something beyond simply returning a partial works EXCELLENT!
EDIT: Also you will need to update your Action...
return Json(new { data = this.RenderPartialViewToString("PartnerApplicationsPartial", objs) });
needs changed to....
return PartialView("PartnerApplicationsPartial", objs);
EDIT BASED ON COMMENTS:
Without knowing the data better that is being sent to the server I can't tell you what to write in order to replace that method. I would however look at the properties of new AjaxOptions(){} because it has some additional properties that allow you to specify the name of a JavaScript function to call on four states (before/after/success/fail) of the Ajax request. So if you are needing to calculate something you can do this by specifying a JavaScript function that will be processed before the Ajax request is submitted.
Also you are doing a lot more work then needed to get the selected radio button value (especially since you are using jQuery).
You can replace...
var radio_check_val=0;
for (i = 0; i < document.getElementsByName('radio').length; i++) {
if (document.getElementsByName('radio')[i].checked) {
radio_check_val = document.getElementsByName('radio')[i].value;
}
}
with something similar to....
var radio_check_val = $('radio').filter(':checked').val();
//this will only work if there is only one set of radio buttons on the page.
//Otherwise you will need to add a name to the selector.
You should not RedirectToAction. Instead of redirect return PartialView('Registration');.
Related questions:
MVC Return Partial View as JSON.
Load PartialView for AJAX and View for non-AJAX request
here's my action.
public virtual JsonResult AddSearch()
{
var data = new { Id = food.Id, Image = food.Image, Name = food.Name};
return Json(data, JsonRequestBehavior.AllowGet);
}
here's my aJax form
#using (Ajax.BeginForm("AddSearch", "Home", new AjaxOptions { OnSuccess = "AddSearch" }))
my javascript file.
function AddSearch() {
alert("sdfsdfsdf");
}
it works, I see the alert box. my question is how I can get the "Id", "Name" and "Image" returned by JsonResult. I tried
alert("sdfsdfsdf");
it's not working.
MVC (to be precise unobtrusiveAjax helpers) will pass the standard jQuery.ajax success(data, textStatus, jqXHR)callback arguments to the OnSuccess method.
So you just need to add the parameters to your AddSearch method:
function AddSearch(data, status, xhr) {
// you can access your properties from data
alert(data.Name);
}
This is how i did... I accessed the list in my model and converted it to a JSON in my javascript.
var JsonServerList = <%= new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(#Model.ServerList) %>;
Now when i say ServerList[i].servername i get the values.
You can try something like this:
In the controller:
public virtual JsonResult AddSearch()
{
var data = new { Id = food.Id, Image = food.Image, Name = food.Name};
return Json(data, JsonRequestBehavior.AllowGet);
}
In the view/javascript section:
function AddSearch() {
$.getJSON("#url.Action(here_goes_your_actionname)", { parameters }, function (data) {
alert(data);
});
}
Hope this helps.
There is one more property in AjaxOption "UpdateTargetId" where your response will append.
your View like
<div id="tagetId">
</div>
#using (Ajax.BeginForm("AddSearch", "Home", new AjaxOptions { OnSuccess = "AddSearch", UpdateTargetId = "tagetId" }))
{
}
In your Controller
public Actionresult AddSearch()
{
var data = new { Id = food.Id, Image = food.Image, Name = food.Name};
return data;
}
you result will be Append in "targertId".