Rendering a partial view with ajax - ajax

Currently I have a main view called getRolesByYear.cshtml. In this view I have three buttons, each for an year. When I click a button(or on page load) I invoke a method, which takes an int 'year' for a parameter and calls an ajax with the year parameter. This ajax calls an action method (getRolesByYear, the one for the main view). The Action method makes a query to a database, a result of which is a list of ViewModel objects. In the return statement I return a PartialView like this : return PartialView("_yearlyRoles",list);. Sadly, after all this, instead of getting a list of the desired objects in my frontend, all i get is an error from the error part of the ajax call. I am generally a novice and I am very stuck with this.
Here is the main view getRolesByYear.cshtml:
#{
ViewBag.Title = "getRolesByYear";
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
getRolesForYear(parseInt(#DateTime.Now.Year));
$(function () {
$('#years a').click(function () {
var year = $(this).text();
console.log(year);
getRolesForYear(parseInt(year));
});
})
//console.log(year);
function getRolesForYear(year) {
console.log(year);
$.ajax({
type: "POST",
url: '#Url.Action("getRolesByYear", "WorkRoles")',
dataType: "json",
data: {
year: year
},
success: successFunc,
error: errorFunc
});
function successFunc(data, status) {
$("#partial").html(data);
}
function errorFunc() {
alert('error');
}
}
</script>
<div id = "years" class="btn-group btn-group-justified timeline">
#DateTime.Now.Year
#DateTime.Now.AddYears(-1).Year
#DateTime.Now.AddYears(-2).Year
</div>
<div id = "partial"></div>
The partial view :
#model IEnumerable<eksp.Models.RoleViewModel>
#foreach (var item in Model)
{
<div class="jumbotron">
<h2>item.Role.RoleName</h2>
<h1> item.Role.RoleDescription</h1>
<p class="lead">Focus start : item.Role.FocusStart</p>
<p>Focus end : item.Role.FocusStart </p>
</div>
}
The Action Method :
[HttpPost]
public ActionResult getRolesByYear(int year)
{
string currentUserId = User.Identity.GetUserId();
var list = db.WorkRoles.
Join(db.WorkRolesUsersDetails,
o => o.WorkRoleId, od => od.WorkRoleId,
(o, od) => new
{
WorkRoleId = o.WorkRoleId,
RoleName = o.RoleName,
RoleDescription = o.RoleDescription,
CompanyId = o.CompanyId,
WRUDId = od.WRUDId,
UserDetailsId = od.UserDetailsId,
FocusStart = od.FocusStart,
FocusEnd = od.FocusEnd
}).ToList()
.Select(item => new RoleViewModel(
item.WorkRoleId,
item.RoleName,
item.RoleDescription,
item.CompanyId,
item.WRUDId,
item.UserDetailsId,
item.FocusStart,
item.FocusEnd)).ToList();
//RoleViewModel rv = list;
if (Request.IsAjaxRequest())
{
return PartialView("_yearlyRoles", list);
}
else
{
return View(list);
}
}

Given the reported error message, you need to alter your ajax call. By setting "data" parameter to "json" you're telling ajax to expect JSON-formatted data back in the response, but a partial view is HTML, so change your ajax call to reflect this:
$.ajax({
type: "POST",
url: '#Url.Action("getRolesByYear", "WorkRoles")/' + year,
dataType: "html", //set the correct data type for the response
success: successFunc,
error: errorFunc
});
As an aside, you can improve your error handling on the client side quite straightforwardly by changing errorFunc to something like this, using the parameters that are provided to the callback by $.ajax:
function errorFunc(jQXHR, textStatus, errorThrown) {
alert("An error occurred while trying to contact the server: " + jQXHR.status + " " + textStatus + " " + errorThrown);
}
For less instrusive reporting and/or easier debugging, you could change the alert to console.log. To get more detail you could also log the entire jQXHR object:
console.log(JSON.stringify(jQXHR));

Related

parameter not send in ajax request

I want to call the action method(AddCompare) using an Ajax request at the View,
My problem is that the parameter sent to AddCompare Action always has zero value,
While the parameter value in the function AddToCompare is correct
this is my code
View:
#model IEnumerable<Products>
#foreach (var item in Model)
{
<li>
<div class="left-block">
<div class="quick-view">
<a title="Add To Compare" class="heart" href="#" onclick="AddToCompare(15)"></a>
</div>
</div>
</li>
}
<script>
function AddToCompare(param) {
alert(param); //display correct value 15
$.ajax({
type: "GET",
url: "#Url.Action("AddCompare")",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({
id: param
}),
success: function (response) {
var myObject = eval('(' + response.d + ')');
if (myObject > 0) {
$(".errMsg").append("<ul><li>Data saved successfully</li></ul>");
}
else {
$(".errMsg").append("<ul><li>Opppps something went wrong.</li></ul>");
}
$(".errMsg").show("slow");
},
error: function (response) {
alert(response.status + ' ' + response.statusText);
}
});
}
</script>
Controller
public JsonResult AddCompare(int id)
{
//id is zero !!!
int param=id;
}
Where is the problem?
try to use
$.get
this is the syntax
$.get(URL,data,function(data,status,xhr),dataType)
In your AJAX call you don't need to stringify
$.ajax({
// your code
data: {id: param},
Decorate your action method with HttpGet even if it is GET by default. Just a better practice.
[HttpGet]
public JsonResult AddCompare(int id)
{
}
Since you are using a Get verb you can do this:
$.ajax({
type: "GET",
url: "/Controller/Action?ID=" + id,
dataType: "json"
}).done(function (response) {
//response code here
});
Change the controller and the action to your needs and you can add other settings to the ajax if needed.

Ajax request off an MVC Form

I am trying to do an ajax request and depending on the ajax request results I will allow the form to submit to the controller. However everytime the ajax request runs I get the error message.
Here is my javascript function:
function CheckForValidation(e) {
var scholarshipRequest = $("#scholars").val();
var aidYearRequest = $("#aidYear").val();
var amountRequest = $("#amount").val();
$.ajax({
type: "POST",
url: '#Url.Action("Validate_ScholarshipRequest", "RequestController")',
data: {
scholarshipId: scholarshipRequest,
aidYear: aidYearRequest,
amount: amountRequest
}
}).success(function(response) {
if (!response.success) {
e.preventDefault();
alert(success);
} else {
e.preventDefault();
}
}).error(function() {
e.preventDefault();
alert("Error on Submission");
});
}
This function is called from here:
$("#SubmitTutorRequestFrm").submit(function(e) {
e.PreventDefault();
CheckForValidation(e);
});
I try to debug the code and put a breakpoint on Validate_ScholarshipRequest but that method never gets called. The method signature is:
public ActionResult Validate_ScholarshipRequest(string scholarshipId, string aidYear, string amount)
This is the start of my form:
#using (Html.BeginForm("SubmitScholarshipRequest", "Request", FormMethod.Post, new { id = "SubmitTutorRequestFrm" }))
Just to get this officially answered and "closed", this was caused by a syntax-error:
url: '#Url.Action("Validate_ScholarshipRequest", "RequestController")',
Controller should not be included in the controller name. The correct action would then be:
url: '#Url.Action("Validate_ScholarshipRequest", "Request")',

AntiforgeryToken works for one form and fails for 2nd form in partialview MVC

So I have a partialview and I have 2 forms inside it as below:
#using (Html.BeginForm("AddAlbum", "Admin", FormMethod.Post, htmlAttributes: new { id = "frmAlbumAdd", novalidate = "novalidate", autocomplete = "off" }))
{
#Html.AntiForgeryToken()
<!--some controls and submit button-->
}
.....
.....
#using (Html.BeginForm("UploadImages", "Admin", FormMethod.Post, htmlAttributes: new { id = "frmUploadImages", novalidate = "novalidate", autocomplete = "off", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<!--some controls and submit button-->
}
and I am doing ajax post to the Admin controller as below:
[HttpPost]
[ValidateAntiForgeryToken]//This works well
public JsonResult AddAlbum(AlbumDataModel model)
{
//perform some task and return result
}
[HttpPost]
[ValidateAntiForgeryToken]//This results in Error
public JsonResult UploadImages([Bind(Prefix = "UIAModel")] UploadImageAlbum model)
{
//perform some task and return result
}
and the error I get on second form submission is "The required anti-forgery form field \"__RequestVerificationToken\" is not present."
According to this post in SO we can have antiforgerytokens for different forms individually. But am not sure why this turns out to be error.
I've also tried adding #Html.AntiForgeryToken() in the Layout where partialviews load and excluded it from forms and had below ajaxSetup to send AntiForgeryToken but even that didn't work.
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
var verificationToken = $("meta[name='__RequestVerificationToken']").attr('content');
if (verificationToken) {
jqXHR.setRequestHeader("X-Request-Verification-Token", verificationToken);
}
});
How can I overcome this issue? What is actually happening here?
UPDATE:
I am using ajax to post the formdata to controller as below:
$.ajax({
url: url,
type: "POST",
dataType: 'json',
data: formData,
processData: false,
contentType: false,
success: function (data) {
}
});
#Html.AntiForgeryToken() generates a hidden input with name="__RequestVerificationToken" so to get the value you need (for the first form)
var verificationToken = $('#frmAlbumAdd [name=__RequestVerificationToken]').val();
and then you can append it to the FormData object using
formData.append('__RequestVerificationToken', verificationToken);
However, since you are using FormData, you can simply serialize all the form controls, including the token and file inputs using
var formdata = new FormData($('#frmAlbumAdd').get(0));
Refer this answer for more details
Can i suggest that you try the following:
$("form").on("submit", function (event) {
event.preventDefault();
var form = $(this);
$.ajax({
url: form.attr('action'),
type: "POST",
data: form.serialize(),
success: function (data) {
//your implementation
},
error: function (jqXhr, textStatus, errorThrown) {
alert("Error '" + jqXhr.status + "' (textStatus: '" + textStatus + "', errorThrown: '" + errorThrown + "')");
},
complete: function () {
//your implementation
}
});
});
This does not uses json as the datatype. Do you really need to use json i like you to take a look at this How can i supply an AntiForgeryToken when posting JSON data using $.ajax?

Update ViewBag dropdownlist with ajax

I am working on cascaded dropdownlist with data passed with dataview.
Controller:
public ActionResult Index()
{
ViewBag.States = new SelectList(db.PLStates, "PLStateID", "PLStateName");
ViewBag.Cities = new SelectList(db.PLCitys, "PLCityID", "PLCityName");
return View();
}
[HttpPost]
public JsonResult GetCity(int SelectedStateId)
{
SelectList result = new SelectList(db.PLCitys.Where(x => x.PLStateID == 3), "PLCityID", "PLCityName");
return Json(result);
//return Json(ViewBag.Cities = new SelectList(db.PLCitys.Where(x => x.PLStateID == 3), "PLCityID", "PLCityName"));
}
HTML:
<script type="text/javascript">
$(document).ready(function () {
$("#States").change(function () {
var SelCity1 = $("#States").val();
$("#Cities").empty();
$.ajax({
type: 'POST',
url: '#Url.Action("GetCity")',
dataType: 'JSON',
data: { SelectedStateId: SelCity1 },
success: function (Cities) {
ViewBag.Cities = Cities;
$("#Cities").append('Cities');
alert("success" + Cities);
},
error: function (ex) {
alert('Failed to retrieve states.' + ex);
}
});
return false;
})
});
</script>
<div>
#Html.DropDownList("States", "Select one")
#Html.DropDownList("Cities", "Select one")
</div>
In alert i can see the json gives back objects but the Cities dropdownlist becomes emptied with no value inside. Why ddl.cities is not filled with retured values??
Additional question is how to add style to dropdownlist??
You will have to manually add options to the cities drop down via js with the Json data returned from the controller.
As far as styling. You can style in inline by adding a "style"= to the html attributes or style with external css class using the #class html attribute.

Returning data from server asp.net mvc action to Jquery Ajax request

I add a link dynamically to a page, and I want the "name" property to be a value that is sent back from server.
This is the code I have for adding a song to the server and then I dynamically append link to my song with a delete button, and I want that button to have a name equal to the songID evaluated on the server side.
$.ajax({
url: "/Home/AddSong",
type: "POST",
data: $("#AddTopTenFavForm").serialize(),
success: function () { ShowMsg("Song Added Successfully"), $(container).find('ul').append('<li><a class="topTenFavLinks" href="#" name="' + substr + '" >' + name + '</a> <span name= #item.SongId class="btnDeleteSong dontDoAnything">x</span></li>'); },
error: function () { ShowMsg("There was an error therefore song could not be added, please try again") }
});
here is my mvc action:
[HttpPost]
public ActionResult AddSong(HomeViewModel songModel)
{
var song = new Song();
song.GenreId = songModel.topTenFav.Rank;
song.Date = DateTime.Now;
song.UserName = User.Identity.Name;
song.Title = songModel.topTenFav.Title;
song.YoutubeLink = songModel.topTenFav.YoutubeLink;
repository.AddSong(song);
repository.Save();
return RedirectToAction("Index");
}
How would I solve this issue in a single ajax request?
You need to return your song ID from the action
[HttpPost]
public ActionResult AddSong(HomeViewModel songModel)
{
//code goes here
return this.Content(song.Id.ToString());
}
and in the javascript success callback you will receive data in arguments:
success: function (data) { /* use data here for anchor name */ },
Use JsonResult to return your Id, and append to your link.
Look at examples
http://shashankshetty.wordpress.com/2009/03/04/using-jsonresult-with-jquery-in-aspnet-mvc/
http://geekswithblogs.net/michelotti/archive/2008/06/28/mvc-json---jsonresult-and-jquery.aspx

Resources