Passing Multiple Parameters to Ajax.ActionLink - razor

I have a view and partial View in my MVC 4 Project. I have 3 textbox, one check box and a dropdown in view.I am using ajax.actionlink method, to call my controller, Action and pass the parameters and get the result from the partial view and display them in the div tag of the view page.
Here is my code.
#Html.TextBoxFor(m=>m.searchParameter.cityName)
#Html.TextBoxFor(m=>m.searchParameter.CountryName)
#Html.TextBoxFor(m=>m.searchParameter.StateName)
#Ajax.ActionLink("submit", "DisplaySearchResult", "Home"
, new { searchParameter = Model.searchParameter }
, new AjaxOptions() { HttpMethod = "Post", UpdateTargetId = "Results", InsertionMode = InsertionMode.Replace }, new { id = "DisplaySearchResult" }).
The problem is am not able to pass the parameters to the model. I am new to MVC4. Is there any way to pass the parameters using jquery or javascript?. I don't want to load the page during my search result.

As I see, you're trying to implement a search form. In this case I avoid using a ViewModel and usually do this:
#Html.TextBox("CityName", string.Empty)
#Html.TextBox("CountryName", string.Empty)
#Html.TextBox("StateName", string.Empty)
Then you can use a bit of jQuery to pass the values to your action method:
$("#submit").click(function() {
var $form = $('form');
$.ajax({
type: "GET",
cache: false,
url: '#Url.Action(ActionName, ControllerName)',
data: $form.serialize(),
success: loadResult
});
function loadResult(data)
{
$("#container").html(data);
}
Just make sure your action method has the appropriate parameters CityName, CountryName, StateName so that the values bind correctly.

Related

Ajax call not working when trying to send & return raw html

I am using Ajax call to invoke C# method that is processing user paste input by removing unwanted html tags and attributes.
When I paste in content with html formatting (tags & attributes), my Ajax call doesn't work. Can you please advise how Ajax parameters should be defined for such scenario (send raw html to server side code and get raw html returned)?
view:
#(Html.Kendo().Editor()
.Name("myEditor")
.PasteCleanup(p => p.Custom("myPasteCleanUp")
)
script:
function myPasteCleanUp(input) {
var response = null;
if (input != null) {
$.ajax({
type: "POST",
url: '/Home/htmlTagCleanUp',
data: { userInput: input },
async: false,
success: function (response) {
input = response;
},
});
}
return input;
}
controller:
[HttpPost]
[AllowAnonymous]
public ActionResult htmlTagCleanUp(string userInput)
{
userInput = userInput;
return Content(userInput, "text/html");
}
It turned out the missing part was sanitizing HTML:
var = document.createElement('div');
element.innerText = html;
var sanitizedHTML = element.innerHTML;
The thing that is preventing your AJAX call is because you have added if conditions:
if (html != null) {
}
Can you tell me where the html variable is defined. Nonetheless, I think you are trying to check the input null values and if we replace the html by input variable on the if the condition it should work:
if (input != null) {
}
I guess the issue is that MVC considers data with tags as a bad request.
Therefore would suggest you try it above the action method in your controller:
[ValidateInput(false)]
Looks like you need to add the [ValidateInput(false)] attribute to your method as it may treat as an XSS attack.
Ref: ValidateInput(false) vs AllowHtml

Asp.net mvc deserialize ajax.beginForm

I need to pass my model, built in this form:
using (Ajax.BeginForm("Index", null, new AjaxOptions() { UpdateTargetId = "FormContainer", HttpMethod = "Post", InsertionMode = InsertionMode.Replace, OnSuccess = "successFunc" }, new { id = "UpdateForm" }))
To this method:
public ActionResult SavePreset(DocumentFilterModel model, string name)
{
//Do some magic
return PartialView("Partial/FilterListPartial", model);
}
The point is that by default, this form will collect report presets, however i need to add and option to save preset in my DB, that is why SavePreset method is needed.
I have tried to use this script:
$("#SavePresetButton").on("click", function () {
$.ajax({
type: "POST",
url: '#Url.Action("SavePreset", "Reports")',
data: {
name: $("#PresetNameEditor").val(),
model: $("#UpdateForm").serialize()
}
}).success(function(result) {
$("#FilterSettingsContainer").html(result);
});
});
But i have encountered a problem, where i either get null in DocumentFilterModel model either (if change model parametr's type to string) can't deserialize it. Things i have tried:
var SettingsModel = new JavaScriptSerializer().Deserialize<DocumentFilterModel>(model);
var a = JsonConvert.DeserializeObject<DocumentFilterModel>(model);
By the way, (these filters located in separate partial view) i would like to keep my form as it is, because i still need to update my second partial view with lists of record, and DocumentFilterModel is too big to parse it manually.
The serialize method reads your form and generates a url encoded string with your input element names and values. So basically it will be a big querystring. When you pass that as the data property of the $.ajax call, jquery will use that for the request body (like FormData)
So when you try something like this
data:{
name: $("#PresetNameEditor").val(),
model: $("#UpdateForm").serialize()
}
It it trying to send an object like this
{name: "Abc", model: "FirstName=Scott&Email=someEmail"}
You can see that you have a js object with 2 properties and the second property has all your input values in a query string format. The model binder cannot read this data and map to your DocumentFilterModel object!.
You cannot mix the result of serialize method to build a js object you want to send as data.
Simply use the result of serialize as the data property value of the ajax call and pass name in querystring.
$("#SavePresetButton").on("click", function () {
$.ajax({
type: "POST",
url: '#Url.Action("SavePreset", "Reports")?name='+$("#PresetNameEditor").val(),
data: $("#UpdateForm").serialize()
}).done(function(result) {
console.log(result);
});
});

MVC5 action that can return either View(model) or json

I have a following problem:
I got an EDIT page, it contains some inputs and so on - nothing unusual. On submit button click I have to validate the form on server and do one of the following actions:
return the model if there are errors
return some info saying it's all good
Why? Because I need to display a bootstrap modal window when everything's ok. So what I did is (simplifying):
[HttpPost]
public ActionResult EditData(DataViewModel model)
{
...
if(!ModelState.IsValid)
return View(model);
return Json(new { success = true, message = "all good" }, JsonRequestBehavior.AllowGet);
}
What is the problem? I'm posting the form with javascript and waiting for the answer like that:
{
$(document).on('click', '#submitButton', function () {
$.ajax({
dataType: "json",
url: "/Controller/EditData",
type: "POST",
data: $('#submitForm').serialize()
}).done(function (data) {
console.log(data.success + ' ' + data.message);
if (data.success) {
$('#modalBody').text(data.message);
$('#modal-window-add').modal('show');
}
});
});
}
So as you can see it does display the modal window but it doesn't do anything when a model comes in. In the latter situation completely nothing happens although the response comes.
Is there any other option to solve my problem? Generally I HAVE to display that modal window on successful edit and on modal closing I need to redirect to another page - this is easy. I tried including the model inside the json but it didn't work and it seems like a lot of work to check all the fields manually and then displaying these red errors under inputs that didn't pass validation. I discussed it with my experienced friends but they don't have any MVC based solution. Any idea?
Best regards,
Daniel
User Ajax For to do that work
#{
var ajaxOptions = new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "modal", OnBegin = "onAjaxBegin", OnComplete = "OnAjaxComplete", OnSuccess = "OnAjaxSuccess" };
}
#using (Ajax.BeginForm("Controler", "EditData", ajaxOptions, new { enctype = "multipart/form-data" }))
{
//write html here with model values
}
COntroller Method
[HttpPost]
public ActionResult EditData(DataViewModel model)
{
if(!ModelState.IsValid)
return View(model);
}
Javascript
function OnAjaxSuccess()
{
show hide model popup
}
$.ajax have a dataType option (The type of data that you're expecting back from the server.)
In $.ajax function you added option dataType: "json" that means you expected json back from server so you will get only json not other dataType like xml, html, text, script
In your case you want to return json or html depending on model is valid or not for that you can remove dateType option from $.ajax function, because If none is specified, jQuery will try to infer it based on the MIME type of the response (an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string).

viewbag data is empty in $.ajax

Iam using asp.net mvc4 and facing some problem in accessing viewbag.price.
This is what i am doing:-
[HttpPost]
public ActionResult FillModel(int id)
{
var vehModel = db.Vehicle_Model.Where(vehMod => vehMod.MakeID == id).ToList().Select(vehMod => new SelectListItem() { Text = vehMod.Model, Value = vehMod.pkfModelID.ToString() });
ViewBag.Price = 100;
return Json(vehModel, JsonRequestBehavior.AllowGet);
}
i am calling above using below:-
$.ajax({
url: '#Url.Action("FillModel","Waranty")',
type: 'post',
data: { id: id },
dataType: 'json',
success: function (data) {
$('#ddModel').empty();
$.each(data, function (index, val) {
var optionTag = $('<option></option>');
$(optionTag).val(val.Value).text(val.Text);
$('#ddModel').append(optionTag);
});
var a = '#ViewBag.Price';
},
error: function () {
alert('Error');
}
});
But i am not able to access ViewBag.Price.
Anyone know the reason??
thanks
The reason you aren't able to access items from the ViewBag inside your ajax success function is because the view that contains your script has already been rendered by the Razor view engine, effectively setting the variable a to whatever the value of #ViewBag.Price was at the time the page was rendered.
Looking at the process flow might be helpful:
(1) The request comes in for the view that has your script fragment in it.
(2) The controller method that returns your view is called.
(3) The Razor view engine goes through the view and replaces any references to #ViewBag.Price in your view with the actual value of ViewBag.Price. Assuming ViewBag.Price doesn't have a value yet, the success function in your script is now
success: function (data) {
$('#ddModel').empty();
$.each(data, function (index, val) {
var optionTag = $('<option></option>');
$(optionTag).val(val.Value).text(val.Text);
$('#ddModel').append(optionTag);
});
var a = '';
}
(4) The rendered html gets sent to the client
(5) Your ajax request gets triggered
(6) On success, a gets set to the empty string.
As you had mentioned in the comments of your question, the solution to this problem is to include a in the Json object returned by your action method, and access it using data.a in your script. The return line would look like
return Json(new {
model = vehModel,
a = Price
});
Keep in mind that if you do this, you'll have to access model data in your ajax success function with data.model.Field. Also, you shouldn't need to specify the JsonRequestBehavior.AllowGet option, since your method only responds to posts and your ajax request is a post.

How to convert JSON array to JavaScript Array?

I am using KnockoutJS for data binding.
Following code is controller's action method
public JsonResult GetPeople()
{
var people = new List<Person>
{
new Person {Name = "aaaa", Address = "aaaaaaaaa"},
new Person {Name = "bbbb", Address = "bbbbbbbbb"},
new Person {Name = "cccc", Address = "ccccccccc"}
};
return Json(people, JsonRequestBehavior.AllowGet);
}
And bellow is the snippet of client side code
<ul data-bind="foreach: people">
<li>NAME:<span data-bind="text: Name"></span></li>
<li>ADDRESS:<span data-bind="text: Address"></span></li>
</ul>
<script>
function getPeopleFromServer() {
var people= [];
$.ajax({
url: "GetPeople",
cache: false,
type: "GET",
success: function (result) {
console.log("result= " + result);
people = $.parseJSON(result);
console.log("people= " + people);
}
});
return people;
}
function ViewModel() {
var self = this;
// data
self.people = ko.observableArray(getPeopleFromServer());
}
ko.applyBindings(new ViewModel());
</script>
The problem is that people variable in the getPeopleFromServer method is always null while result has proper value from the server.
Am I missing something?
Your $.ajax function is taking longer to complete than it's containing function, and so the containing function never popuplates people by the end of execution
One thing you can do is to add the following to your $.ajax:
$.ajax({
async: false,
url: "GetPeople",
.....
});
async: false will make the containing function 'wait' until ajax is finished. Your people var should be populated by the end of function execution. While this is a quick win, I agree with Tom that you should re-think how your ViewModel is handled.
#tom's comment is correct.
'success' is an inline async function. Basically, 'return people' happens before the 'success' function is called, because the ajax call is non-blocking. You need to redesign your ViewModel to work asynchronously (or turn off async), hopefully others will chime in with code fixes
Here's the fully commented fiddle he prophesied.
http://jsfiddle.net/bczengel/8Wqum/
people should be referred to either in the same view model. Or as self.people. I suggest you put the call to ajax inside the view model and then it will be clear.
So getPeopleFromServer() should be inside the viewmodel.
Out of interest you can also add
timeout: 600000 so that the call doesnt timeout.
Try to use ko.mapping plugin.
function ViewModelWrapper(jsonResult)
{
var self = this;
self.model = ko.mapping.fromJS(jsonResult);
}
http://knockoutjs.com/documentation/plugins-mapping.html