ASP.Net MVC model binding to javascript - javascript

The question is pretty straightforward: I use #Html.EditorForModel() to generate fields for my model. Then user fills all these fields and I want to send this field via AJAX, becuase I should do several server's services without page reload.
I googled several approaches, but it seems that there is no standard way to do such things. I mean I do not have an object on client-side that represent model. I found one single library calls JSModel (link) but it seems to be not working. My code for now is:
#model Student
<script src="#Url.Content("~/scripts/jquery-1.12.2.min.js")" type="text/javascript" async="async"></script>
<script src="#Url.Content("~/scripts/Requester.js")" type="text/javascript" async="async"></script>
<script src="#Url.Content("~/scripts/jsmodel.js")" type="text/javascript"></script>
<script type="text/javascript">
var requester = new Requester(#Html.Raw(Json.Encode(new Student())));
function SendSignupRequest() {
requester.SendSignupRequest();
}
</script>
<h2>Student</h2>
<div>
#Html.EditorForModel()
</div>
<input type="button" value="Send" onclick="SendSignupRequest()"/>
Requester.js:
function Requester(rawModel) {
this.modelObj = new JSModel(rawModel);
this.SendSignupRequest = function() {
var model = modelObj.refresh();
var val = model.prop("Name");
alert(val);
}
}
Is there any easy way to serialize a model object in JSON and send it to server, without manually constructing an object with millions of document.getElementById?

View
#using (Html.BeginForm("action", "controller", FormMethod.Post, new { #class = "form-horizontal form-compact ", role = "form", id = "form1" }))
{
}
Java Script
var formdata = $("#form1").serializeArray();
$.ajax({
url: url,
type: 'POST',
data: formdata,
success: function (data) {
}
Controller
public ActionResult action(Model model)
{
//access data here
}

You can serialize your form to a JSON object with jQuery:
var data = $('form').serialize();
(This would, of course, mean wrapping your form elements in a form, which really should be happening anyway.)
Then just pass that data object to the server in the POST request. Something as simple as:
$.post('some/url', data, function(response) {
// success callback
});
without manually constructing an object with millions of document.getElementById
Note that if your object has millions of fields then you may very well encounter other problems here.

Yes you can use form serialize using Jquery
var formData = $('#form').serializeObject();
$.extend(formData, { Contacts : myContacts});
$.extend(formData, { Address : myAddress});
var result = JSON.stringify(formData);
$('#formHiddenField').val(result);
then submit form using:
$.ajax(
url: #Url.Action("post url")
data: myForm.serialize(),
dataType: 'json',
type: 'POST',
success: function(){
})

Why not Ajax.BeginForm() for your purposes. I believe model binding works automatically.

Related

API POST call with large model, need some guidance

I have a fairly large form (50 fields) and I need to pass it into an API call.
Doing it in the javascript file would be pretty large to serialize all the data on the form into the proper model.
Is it possible to call the controller, and use the model from that to pass it through to the api url?
Basically I want to know an easy way to take my form data and turn it into serialized data based on my model.
thanks!
EDIT: Easy meaning that I don't have to take each form input and create my model with them
My code now is basically this below, but I would need to fill out a bunch of fields (I haven't tried it any other way)
$("#submit").click(function () {
var name = $("#Name").val();
var address = $("#Address").val();
var dob = $("#DOB").val();
$.ajax({
url: "http://localhost:49493/api/Values",
type: "Post",
data: JSON.stringify([name, address, dob]),
//instead of 3 fields, I would have 50
contentType: 'application/json; charset=utf-8',
success: function (data) { },
error: function () { alert('error'); }
});
});
jQuery has a function that you can use $("#myForm").serialize()
http://api.jquery.com/serialize/
$("#submit").click(function () {
var myData = $("#myForm").serialize()
$.ajax({
url: "http://localhost:49493/api/Values",
type: "Post",
data: myData,
//instead of 3 fields, I would have 50
contentType: 'application/json; charset=utf-8',
success: function (data) { },
error: function () { alert('error'); }
});
});
(Although a 50 form field sounds quite large. You might want to reconsider your design, but perhaps there is a valid use case)
A javascript MV* framework can be helpful here (I'm most familiar with angular). With angular, you can define a binding between your UI elements and the underlying javascript model representation (which can be sent to your Web API with the $http service).
Here is a language agnostic way to iterate over elements and build a model. It was done quick and dirty, and there is much room for improvement (i.e. using addEventListener, attachEvent, then onclick, etc.) -- but jquery handles much of this for you, so would suggest to stick with using that. This could easily be converted over to jQuery... The javascript iterates over input elements and adds them to a model object. This object can then be sent over AJAX if desired. The example just outputs it to a div placeholder.
http://jsfiddle.net/T9MyZ/
JavaScript:
document.getElementById("submitMe").onclick = function () {
var inputs = document.getElementsByTagName("input");
var model = {};
for (var i = 0, len = inputs.length; i < len; i++) {
var elem = inputs[i];
model[elem.name] = elem.value;
}
document.getElementById("jsonText").innerHTML = JSON.stringify(model);
};
HTML:
<input type="text" name="name"><br>
<input type="text" name="address"><br>
<input type="text" name="dob"><br>
<button id="submitMe">Submit</button>
<br>
<div id="jsonText"></div>

ASP.NET MVC3 form collection is 0 during jQuery ajax post

I am working on an ASP.NET MVC3 application.
I am attempting to POST to a method that returns a bunch of data using the jQuery.ajax api; however whenever the request is handled by the server my form collection's keys count is 0 and so my view model isn't populated which is a problem.
I am applying applying the ajax to my form's submit like this:
$(document).on("submit", "form", function (event) {
event.preventDefault();
var form = $(this);
$.ajax({
type: "POST",
url: this.action,
data: form.serialize(),
contentType: "application/html; charset=utf-8",
dataType: "html",
success: function (result) {
var d = new Date();
var str = d.toString() + result;
$('#dynamicContent').html(str);
}
});
});
My form is created like this:
#Using Html.BeginForm("GetContent", "TheController", FormMethod.Post, New With {.id = "GetContentForm"})
#Html.DropDownListFor(Function(model) model.SelectedTypeID, New SelectList(Html.NullListItemOptionList(Model.TypeOptions.ToList, "Please Choose"), "ID", "Name", Model.SelectedTypeID), New With {.onchange = " $(this).parents('form').submit();"})
#<input type="submit" value="Refresh" style="cursor: pointer" />
End Using
<div id="dynamicContent">
</div>
My controller method is:
<HttpPost()>
Function GetContent(ByVal collection As FormCollection) As PartialViewResult
Dim itemsVM As New ItemsViewModel
TryUpdateModel(itemsVM, collection)
Return PartialView("PartialItems", itemsVM)
End Function
It's almost as if the serialization of the form is not working but I don't know how to fix this. I would really appreciate some insight into why this isn't working.
Thank you.
Since you're sending form params, the contentType you are using is incorrect, which in turn causes the server to not receive your data because it's expecting html and is not receiving any. To solve it, simply remove the contentType option from $.ajax.

Url.Content for javascript

I currently use this approach to obtain the correct relative URI (independent of the deployment situation). Razor code (asp.net mvc 3):
#section JavaScript
{
<script type="text/javascript">
var _getUrl = "#Url.Content("~/bla/di/bla")";
</script>
}
Separate js file:
$.ajax({
url: _getUrl,
Do you reckon there is a better approach?
Personally I prefer using HTML5 data-* attributes or including the URL as part of some DOM element that I unobtrusively AJAXify.
The thing is that you never write $.ajax calls flying around like that. You write them to correspond to some DOM events. Like for example clicking of an anchor. In this case it's trivial, you just use an HTML helper to generate this anchor:
#Html.ActionLink("click me", "someAction", "somecontroller", new { id = "123" }, new { #class = "link" })
and then:
$('.link').click(function() {
$.ajax({
url: this.href,
type: 'GET',
success: function(result) {
...
}
});
return false;
});
or maybe you are AJAXifying a form:
#using (Html.BeginForm("SomeAction", "SomeController", FormMethod.Post, new { id = "myForm" }))
{
...
}
and then:
$('#myForm').submit(function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
...
}
});
return false;
});
Another example would be to use HTML5 data-* attributes when an appropriate url is not available on the corresponding DOM element. Suppose that you want to invoke a controller action with AJAX when the selection of a dropdown changes. Think for example cascading ddls.
Here's how your dropdown might look like:
#Html.DropDownListFor(x => x.SelectedValue, Model.Values, new { id = "myDdl", data_url = Url.Action("SomeAction") })
and then:
$('#myDdl').change(function() {
var url = $(this).data('url');
var selectedValue = $(this).val();
$.getJSON(url, { id: selectedValue }, function(result) {
...
});
});
So as you can see you don't really need this _getUrl global javascript variable that you declared in your view.
I would do the following:
Razor C# script before Javascript
#{
var myUrlString = Url.Action("ActionName", new { controller="ControllerName" });
}
JavaScript
$.ajax('#myUrlString',{
// options
});
You could also use Url.RouteUrl or Url.HttpRouteUrl.
EDIT - showing example with separated JS file
Razor
#{
var myServerGeneratedValue = Url.Action("ActionName", new{controller="ControllerName"});
}
<script type="text/javascript">
var myHelperObject = new MyHelperObject();
myHelperObject.Init('#myServerGeneratedValue');
</script>
JS file
var MyHelperObject = function(){
this.Init = function(serverGeneratedValue){
// do something with serverGeneratedValue
};
};

submit a form with jQuery function

i have a html page, which contains a form and i want when the form is successfully submited, show the below div:
<div class="response" style="display: none;">
<p>you can download ithere</p>
</div>
i also have a jquery function:
<script type="text/javascript">
$(function() {
$('#sendButton').click(function(e) {
e.preventDefault();
var temp = $("#backupSubmit").serialize();
validateForm();
$.ajax({
type: "POST",
data: temp,
url: 'backup/',
success: function(data) {
$(".response").show();
}
});
});
});
</script>
and in my views.py (code behind) i create a link and pass it to html page. i have:
def backup(request):
if request.is_ajax():
if request.method=='POST':
//create a link that user can download a file from it. (link)
variables = RequestContext(request,{'link':link})
return render_to_response('backup.html',variables)
else:
return render_to_response('backup.html')
else:
return render_to_response("show.html", {
'str': "bad Request! :(",
}, context_instance=RequestContext(request))
backup = login_required(backup)
my problem: it seems that my view doesn't execute. it doesn't show me the link that i send to this page. it seems that only jQuery function is executed. i'm confused. how can i make both of them to execute(i mean jQuery function and then the url i set in this function which make my view to be executed.)
i don't know how to use serialize function. whenever i searched, they wrote that:
The .serialize() method creates a text string in standard URL-encoded notation and produces query string like "a=1&b=2&c=3&d=4&e=5.
i don't know when i have to use it, while i can access to my form field in request.Post["field name"]. and i don't know what should be the data which is in success: function(data) in my situation.
thank very much for your help.
You have to get and display the data from your ajax post function, where data is the response you render through your DJango server, for example:
t = Template("{{ link }}")
c = Context({"link": link})
t.render(c):
Your JS / jQuery should become something like this:
<script type="text/javascript">
$(function() {
$('#sendButton').click(function(e) {
e.preventDefault();
var temp = $("#backupSubmit").serialize();
validateForm();
$.ajax({
type: "POST",
data: temp,
url: 'backup/',
success: function(data) {
// 'data' is the response from your server
// (=the link you want to generate from the server)
// Append the resulting link 'data' to your DIV '.response'
$(".response").html('<p>you can download ithere</p>');
$(".response").show();
}
});
});
});
</script>
Hope this helps.

Calling ASP.NET MVC Action Methods from JavaScript

I have sample code like this:
<div class="cart">
<a onclick="addToCart('#Model.productId');" class="button"><span>Add to Cart</span></a>
</div>
<div class="wishlist">
<a onclick="addToWishList('#Model.productId');">Add to Wish List</a>
</div>
<div class="compare">
<a onclick="addToCompare('#Model.productId');">Add to Compare</a>
</div>
How can I write JavaScript code to call the controller action method?
Use jQuery ajax:
function AddToCart(id)
{
$.ajax({
url: 'urlToController',
data: { id: id }
}).done(function() {
alert('Added');
});
}
http://api.jquery.com/jQuery.ajax/
Simply call your Action Method by using Javascript as shown below:
var id = model.Id; //if you want to pass an Id parameter
window.location.href = '#Url.Action("Action", "Controller")/' + id;
You are calling the addToCart method and passing the product id. Now you may use jQuery ajax to pass that data to your server side action method.d
jQuery post is the short version of jQuery ajax.
function addToCart(id)
{
$.post('#Url.Action("Add","Cart")',{id:id } function(data) {
//do whatever with the result.
});
}
If you want more options like success callbacks and error handling, use jQuery ajax,
function addToCart(id)
{
$.ajax({
url: '#Url.Action("Add","Cart")',
data: { id: id },
success: function(data){
//call is successfully completed and we got result in data
},
error:function (xhr, ajaxOptions, thrownError){
//some errror, some show err msg to user and log the error
alert(xhr.responseText);
}
});
}
When making ajax calls, I strongly recommend using the Html helper method such as Url.Action to generate the path to your action methods.
This will work if your code is in a razor view because Url.Action will be executed by razor at server side and that c# expression will be replaced with the correct relative path. But if you are using your jQuery code in your external js file, You may consider the approach mentioned in this answer.
If you do not need much customization and seek for simpleness, you can do it with built-in way - AjaxExtensions.ActionLink method.
<div class="cart">
#Ajax.ActionLink("Add To Cart", "AddToCart", new { productId = Model.productId }, new AjaxOptions() { HttpMethod = "Post" });
</div>
That MSDN link is must-read for all the possible overloads of this method and parameters of AjaxOptions class. Actually, you can use confirmation, change http method, set OnSuccess and OnFailure clients scripts and so on
If you want to call an action from your JavaScript, one way is to embed your JavaScript code, inside your view (.cshtml file for example), and then, use Razor, to create a URL of that action:
$(function(){
$('#sampleDiv').click(function(){
/*
While this code is JavaScript, but because it's embedded inside
a cshtml file, we can use Razor, and create the URL of the action
Don't forget to add '' around the url because it has to become a
valid string in the final webpage
*/
var url = '#Url.Action("ActionName", "Controller")';
});
});
Javascript Function
function AddToCart(id) {
$.ajax({
url: '#Url.Action("AddToCart", "ControllerName")',
type: 'GET',
dataType: 'json',
cache: false,
data: { 'id': id },
success: function (results) {
alert(results)
},
error: function () {
alert('Error occured');
}
});
}
Controller Method to call
[HttpGet]
public JsonResult AddToCart(string id)
{
string newId = id;
return Json(newId, JsonRequestBehavior.AllowGet);
}
You can simply add this when you are using same controller to redirect
var url = "YourActionName?parameterName=" + parameterValue;
window.location.href = url;
You can set up your element with
value="#model.productId"
and
onclick= addToWishList(this.value);
I am using this way, and worked perfectly:
//call controller funcntion from js
function insertDB(username,phone,email,code,filename) {
var formdata = new FormData(); //FormData object
//Iterating through each files selected in fileInput
formdata.append("username", username);
formdata.append("phone", phone);
formdata.append("email", email);
formdata.append("code", code);
formdata.append("filename", filename);
//Creating an XMLHttpRequest and sending
var xhr = new XMLHttpRequest();
xhr.open('POST', '/Home/InsertToDB');//controller/action
xhr.send(formdata);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
//if success
}
}
}
in Controller:
public void InsertToDB(string username, string phone, string email, string code, string filename)
{
//this.resumeRepository.Entity.Create(
// new Resume
// {
// }
// );
var resume_results = Request.Form.Keys;
resume_results.Add("");
}
you can find the keys (Request.Form.Keys), or use it directly from parameters.
You can easily make a <a> link in your view.
<a hidden asp-controller="Home" asp-action="Privacy" id="link"></a>
then in you javascript code use this:
location.href = document.getElementById('link').href;

Categories