Send Multiple objects with Ajax to the ASP.NET MVC controller - javascript

I have one ViewModel that contains three Collection of ExternalProjectViewModel, CertificateUniverSityViewModel, CertificateInstitutionsViewModel.
CreateFreelancerProfileViewModel.cs
public class CreateFreelancerProfileViewModel : BaseViewModel
{
// More ...
public List<ExternalProjectViewModel> ExternalProjects { get; set; }
public List<CertificateUniverSityViewModel> CertificateUniverSitys { get; set; }
public List<CertificateInstitutionsViewModel> CertificateInstitutions { get; set; }
}
My Ajax code:
$('#Controller').on('click','#SaveProfile',
function() {
debugger;
var CertificateInstitutions =
JSON.parse(localStorage.getItem("CertificateInstitutionsListLocal"));
var CertificateUniverSitys =
JSON.parse(localStorage.getItem("CertificateUniverSitysListLocal"));
var ExternalProjects =
JSON.parse(localStorage.getItem("ExProjectListLocal"));
$.ajax({
url : '#Url.Action(MVC.Freelancer.Profile.CreatePrfile())',
method: "POST",
data: {
ExternalProjects,
CertificateUniverSitys,
CertificateInstitutions
}
});
});
When I Want Send Objects to Controller, First Get It from LocalStorage
And After Get it Send it to Controller Action:
public virtual ActionResult CreatePrfile(CreateFreelancerProfileViewModel viewModel)
When I see viewModel Values Show My Objects Count That is 2 but Objects Properties is null.so that my server object properties name equally with the client Object properties name.
LocalStorage Values
[{"ExternalProjects":{"Name":"wqeqwe","Body":"wqewqe","Url":‌​"wqewqe"}}]
[{"CertificateUniverSity":{"Name":"sad","Description":"sadas‌​","DateOfGets":"sad"‌​,"CertificateType":"‌​2","Field":"sadasd",‌​"UniName":"sad","Cer‌​tificateUniverSityLe‌​vel":"2"}}]

You could send them as JSON payload:
$.ajax({
url : '#Url.Action(MVC.Freelancer.Profile.CreatePrfile())',
method: 'POST',
contentType: 'application/json',
data: JSON.stringify({
externalProjects: ExternalProjects,
certificateUniverSitys: CertificateUniverSitys,
certificateInstitutions: CertificateInstitutions
}),
success: function(result) {
alert('data sent successfully');
}
});
This assumes that the instances you got from the localStorage of those 3 variables represent javascript arrays with the corresponding objects in it.

Related

Access form data in C# controller from AJAX post

I am sending form data to a c# controller using AJAX, however I don't know how to access the data inside the controller. I am trying to pass the form data into the controller as a Person object but I am just returning system.Models.Person. I am new to C# so any help would be greatly appreciated, thanks a lot.
Javascript
$('#myForm').submit(function(e){
e.preventDefault();
const formData = new FormData(e.target);
$.ajax({
url: '/Home/GetFormData',
type: 'POST',
data: {formData: formData},
success: function(resultData){
console.log(resultData)
},
error: function(){
//do something else
}
})
}
Model
public class Person
{
public string name { get; set; }
public string age { get; set; }
}
Controller
public string GetFormData(Person formData)
{
string name = formData.name.ToString();
return name;
}
The following post will help you
Post Data Using jQuery in ASP.NET MVC
Your code should be
Model class Person.cs
public class Person
{
public string name { get; set; }
public string age { get; set; }
}
jQuery function to get the form data, I am assuming here you have submit button on your form
$(document).ready(function () {
$("#btnSave").click(function () { //Your Submit button
$.ajax(
{
type: "POST", //HTTP POST Method
url: "Home/GetFormData", // Controller/View
data: { //Passing data
name: $("#txtname").val(), //Reading text box values using Jquery
age: $("#txtage").val(),
}
});
});
});
Your HomeController method
[HttpPost]
public ActionResult GetFormData(Person obj)
{
string name = obj.name;
string age = obj.age;
//Once you have data here then you can pass anywhere i.e. database or some other method
return View();
}
Form values in the controller
Let me know, if any clarification required.
Use serialize if you will send form values:
$form = $(this).serialize();
Use FormData if you be sending a file for upload and alike.
And on your data declaration, set it as is (without declaring it as a literal JS object)
data: $form
The final code would look like this:
$('#myForm').submit(function(e){
e.preventDefault();
$form = $(this).serialize();
$.ajax({
url: '/Home/GetFormData',
type: 'POST',
data: $form,
success: function(resultData){
console.log(resultData)
},
error: function(){
//do something else
}
})

Passing objects from Ajax to C# WebApi

I’m still not fluent in calling WebAPI services. I succeed in simple items, but now my needs are getting complicated and things always fail.
I use MVC 5 for WebAPI, and call using regular jQuery functions.
My Model
Here I manage appointments of patients in a clinic. I use the following model for Patient and Appointment entities:
public class Patient
{
// Personal data
public int Id { get; set; }
public string Name { get; set; }
}
public class Appointment
{
public int Id { get; set; }
public DateTime Date { get; set; } // date only
public int Order { get; set; }
public string PatientName { get; set; }
// Parent data
public Patient Patient { get; set; }
public int PatientId { get; set; }
public Organization Organization { get; set; }
public int OrganizationId { get; set; }
}
My DTOs
public class AppointmentDto
{
public int Id { get; set; }
public int Order { get; set; }
public string PatientName { get; set; }
public PatientDto Patient { get; set; }
}
public class PatientDto
{
public string Name { get; set; }
}
First Case
I want to set new ordering for appointments within a day. I send list of JSON objects with IDs of appointments to be changed and their respective orders.
The service action:
[HttpPost]
public IHttpActionResult UpdateOrder(List<AppointmentDto> dto)
{
_unitOfWork.Appointments.UpdateOrder(dto);
_unitOfWork.Complete();
return Ok();
}
The service call:
// Handler methods
var rearrangeAppointments = function (event, ui) {
// Json object to pass
var orderedAppointments = [];
// Looping through appointments
var i = 0;
$("#sortable").children().each(function () {
// Set new order
i++;
orderedAppointments.push({ "Id": this.getAttribute("data-id").toString(), "Order": i.toString() });
});
// Call service
appointmentsService.updateOrder(orderedAppointments, done, fail);
};
var updateOrder = function (orderedAppointmens, done, fail) {
$.ajax({
url: "/api/appointments",
method: "POST",
data: orderedAppointmens,
dataType: "Json"
})
.done(done)
.fail(fail);
};
The service is called successfully, but the passed list is always empty. I debugged the JavaScript code and the array of JSON object is built successfully. Also debugged the MVC code and tested the service Postman, it works very fine. This drop is passing the list of objects from client to server.
Second Case
This time it’s a get call. I want to get list if appointments if a specific date to update the view.
The service action:
public IEnumerable<AppointmentDto> GetAppointments(DateTime date)
{
var organizationId = _unitOfWork.ApplicationUsers.GetOrganizationId(User.Identity.GetUserId());
var appointments = _unitOfWork.Appointments.GetAppointments(date, organizationId);
return appointments.Select(Mapper.Map<Appointment, AppointmentDto>);
}
The service call:
$("#datepicker").datepicker({
// TODO: Refactor to pettern
onSelect: function (dateText, inst) {
var selectedDate = $(this).datepicker('getDate');
var date = JSON.stringify(selectedDate);
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: "json",
url: "/api/appointments",
data: date,
success: function (appointments) {
alert("Service call succeeded!")
alert(appointments.length);
}
})
.fail(function () {
alert("Failure!");
});
}
});
When I test the code without passing a date (hardcoding the date into the action method) it works very well. When I add the date to the parameters (in the action method and the AJAX call), it does not work at all.
I've tried many links and articles from here and other sources with no success, like below:
Pass a datetime from javascript to c# (Controller)
Pass Date Values from Ajax Call to MVC
and more that I could not add here.
I think my major problem in the two cases in passing data.
What am I missing here?
for the second case : Do you sent date-time ?? if you do that the URL may contains ":" (12:00) & this type of character is denied by the HTTP request
After some tracing with one friend, and reviewing some other articles and questions...
First Case (passing list of objects)
I reformatted the array of objects using JSON.stringify(orderedAppointmens), and added contentType: 'application/json; charset=utf-8' to the service call. The code should look like below:
var updateOrder = function (orderedAppointmens, done, fail) {
orderedAppointmens = JSON.stringify(orderedAppointmens);
$.ajax({
url: "/api/appointments",
method: "POST",
data: orderedAppointmens,
contentType: 'application/json; charset=utf-8',
dataType: "Json"
})
.done(done)
.fail(fail);
};
Second Case (passing a Date object)
I removed the Json dataType from the service call and concatenated the date to the URL like below:
$.ajax({
url: "/api/appointments?date=" + selectedDate.toISOString(),
type: "GET",
success: function (appointments) {
alert(appointments.length);
}
});
This worked fine and the Date object is passed to the DateTime object in backend successfully.

How to pass a javascript object to a C# MVC 4 controller

In MVC4, how do you pass a javascript object to a C# controller in AJAX?
Finally I tried this but it did not work.
Javascript Client side:
var myData = {Propr1: '', Propr2: ''};
$.ajax({
type: 'POST',
data: JSON.stringify(myData),
url: '/Home/SubmitMyData',
contentType: 'application/json',
dataType: 'json',
success: alert('Youhou'),
error: alert('not good')
});
C# Server side method:
public ActionResult SubmitMyData(MyParamModel myParam)
{
// Do my stuff here with my parameter
return View();
}
public class MyParamModel
{
string Prop1 { get; set; }
string Prop2 { get; set; }
}
My parameter is always null. I tried to change the contentType but it still not work.
Where are my mistakes? I found some posts but I did not find what I did wrong.
Thanks a lot.
Make sure the property names match between the javascript and the C# model. In your question you had Propr1 and Propr2 for the javascript object, but in the C# model you had Prop1 and Prop2 (missing the "r").
Do not stringify the data before sending it, and do not set dataType to json. MVC can parse just fine with a collection of post parameters without the json serialization in your code.
Omit the contentType, it is not necessary. WebAPI should autodetect this. You can leave it, but it's extraneous.
Make sure the model properties are public.
Javascript Client side:
var myData = {Prop1: '', Prop2: ''}; // #1
$.ajax({
type: 'POST',
data: myData, // #2
url: '/Home/SubmitMyData',
//contentType: 'application/json', #3
//dataType: 'json', #2
success: alert('Youhou'),
error: alert('not good')
});
C# Server side method:
public ActionResult SubmitMyData(MyParamModel myParam)
{
// Do my stuff here with my parameter
return View();
}
public class MyParamModel // #4
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
The value you pass for the data property should be an object, not a string:
data: myData,
the property names need to match:
var myData = { Prop1: '', Prop2: ''};
you need to use the [FromBody] attribute on your parameter value:
public ActionResult SubmitMyData([FromBody] MyParamModel myParam)
and the properties on your model type need to be public:
public class MyParamModel
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}

ajax post on MVC .NET does not pass array correctly

I have a simple modal that uses select2 to get a list of Products from the server. User can multiple choose products and hit Ok to refine a search.
My following setup grabs the data from the modal and does an ajax call against a Controller action with a strongly typed view model that matches what the JS is trying to send via the ajax call.
Ajax:
var exploreFilters = {
"type" : exploreType,
"products" : $('#s2id_select2-products').select2('data'),
"locations" : $("#page-report__data").data("criteria__locations"),
"companies" : $("#page-report__data").data("criteria__companies"),
"usertypes" : $("#page-report__data").data("criteria__usertypes"),
"groupusers" : $("#page-report__data").data("criteria__groupusers"),
"datestart" : $("#page-report__data").data("criteria__datestart"),
"dateend" : $("#page-report__data").data("criteria__dateend")
};
$.ajax({
dataType: "html",
type: "POST",
url: "/Report/Group/FilteredView",
data: exploreFilters,
success: function(html) {
if($.trim(html) === "")
$targetSection.html('<div class="page-report__empty">No data found. Please adjust your search filters and try again.</div>');
else
$targetSection.html(html);
},
error: function(xhr, text, err) {
if(text === "timeout")
$targetSection.html('<div class="page-report__empty">The request timed out. Please try again.</div>');
else
$targetSection.html('<div class="page-report__empty">There has been an error.</div>');
}
});
Right before the ajax call goes to the controller I inspect the content and structure of exploreFilters:
Here is how the form data looks on the POST request:
On the other side I got a controller which takes a strongly-typed parameter with a structure similar to what exploreFilters has:
public ActionResult FilteredView(ReportCriteriaViewModel criteria)
{
throw new NotImplementedException();
}
And my strongly-typed view model:
public class ReportCriteriaViewModel
{
public ProductViewModel[] Products { get; set; }
public string[] Locations { get; set; }
public string[] Companies { get; set; }
public string UserTypes { get; set; }
public string GroupUsers { get; set; }
public string DateStart { get; set; }
public string DateEnd { get; set; }
}
public class ProductViewModel
{
public Guid Id { get; set; }
public string Text { get; set; }
}
Once the controller action gets hit I can see that DateStart and DateEnd have been successfully bound but not my list of products.
I cannot change the datatype on the json request, it has to be html because my controller action is going to be returning html.
I've tried changing the capitalization on Id and Text, JSON.stringify (which actually makes the dates not bind anymore)
What am I doing wrong?
Try to add contentType: "application/json" in your Ajax request
$.ajax({
...
contentType: "application/json",
...
});
The problem is in how you are serializing the list:
products[0][id]
products[0][text]
You need to send your list in this format:
products[0].id
products[0].text
id and text should be properties, without the [] otherwise it is treated as an index to a two-dimensional array.
You should try
contentType: "application/json; charset=utf-8"
in the options of the $.ajax call
$.ajax({
dataType: "html",
type: "POST",
url: "/Report/Group/FilteredView",
data: exploreFilters,
contentType: "application/json; charset=utf-8" ....

How can I bind a simple Javascript array to an MVC3 controller action method?

Here is the javascript code I use to create the array and send it on it's way:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
$("#update-cart-btn").click(function() {
var items = [];
$(".item").each(function () {
var productKey = $(this).find("input[name='item.ProductId']").val();
var productQuantity = $(this).find("input[type='text']").val();
items[productKey] = productQuantity;
});
$.ajax({
type: "POST",
url: "#Url.Action("UpdateCart", "Cart")",
data: items,
success: function () {
alert("Successfully updated your cart!");
}
});
});
});
</script>
The items object is properly constructed with the values I need.
What data type must my object be on the backend of my controller?
I tried this but the variable remains null and is not bound.
[Authorize]
[HttpPost]
public ActionResult UpdateCart(object[] items) // items remains null.
{
// Some magic here.
return RedirectToAction("Index");
}
If you are going to send JSON to the server you need to JSON.stringify the data and specify the contentType as application/json to play nice with the MVC3 model binder:
$.ajax({
type: "POST",
url: "#Url.Action("UpdateCart", "Cart")",
data: JSON.stringify(items),
success: function () {
alert("Successfully updated your cart!");
},
contentType: 'application/json'
});
And as the datatype on the server you can use strongly typed classes eg:
public class Product
{
public int ProductKey { get; set; }
public int ProductQuantity { get; set; }
}
[HttpPost]
public ActionResult UpdateCart(Product[] items)
{
// Some magic here.
return RedirectToAction("Index");
}
But you need to tweak the items list a bit:
var items = [];
$(".item").each(function () {
var productKey = $(this).find("input[name='item.ProductId']").val();
var productQuantity = $(this).find("input[type='text']").val();
items.push({ "ProductKey": productKey, "ProductQuantity": productQuantity });
});
Basically the JSON object structure should match the C# model class structure (also the property name should match) and then the model binder in MVC takes care to populate your server side models with the JSON data that you've sent. You can read more about model binders here.

Categories

Resources