How to send IEnumerable list from Ajax to Controller - javascript

I have a web application in MVC3 and i'm using Telerik Grid Batch Editing.
Batch Editing have save changes button which returns UPDATED COLUMNS to controller IEnumerable list like
[GridAction]
public ActionResult Update(IEnumerable<Customers> updated)
{
///user codes
}
but how to collect updated rows and make array send like IEnumerable list from Javascript with ajax to Controller ?
EDIT
I'm putting my view png
I just want to send updated rows data to Controller and Save Changes button can do this but before thje send values i just want to ask to user "Are you sure to Load?" and after the send data I want to refresh all the page
So i thinked to do this with ajax request because i'm also using batch editing with ajax requests
Do you have any exprience for this situation?

Use the AJAX POST as I have used in my Tested Javascript function as::
function TestAjax() {
var Test = [];
for (var i = 0; i < 5; i++) {
Test.push({ ID: i, Name: "RJ" });
}
$.ajax({
type: 'POST',
url: rootUrl('Home/TestPost'),
contentType: "application/json",
//data: { Test: JSON.stringify( data) },
data:JSON.stringify( {Test: Test}),
success: function (data) {
alert("Succeded");
}
});
}
And on Server Side(i.e. In Controller) use something Like::
public ActionResult TestPost(IEnumerable<TestViewModel> Test)
{
return Json(3);
}
The ViewModel Contains different propeties which are of different datatypes as::
public class TestViewModel
{
public long ID { get; set; }
public string Name { get; set; }
}
This is working fine. May be this will help you.

Related

Post knockout.js viewmodel to .Net Core (2.0) MVC Controller

Overview:
Currently, I try to create an ASP.NET Core MVC website which gets data from the server on page load. After that, the page uses knockout.js to maintain a viewmodel to update the data sent from the server (in the first step). Finally, there is a button which sends the edited data back to the server (through an AJAX request). But the corresponding value in my server method is always empty.
Current Approach:
First, there is my model class.
public class Order
{
public string Name { get; set; }
public int TemplateId { get; set; }
public decimal Price { get; set; }
public int Contingent { get; set; }
public int MaximumOrder { get; set; }
public int UserOrderCount { get; set; }
public Order() { }
public Order(SnackOffer offer)
{
Name = offer.Template.Name;
TemplateId = offer.Template.SnackTemplateId;
Price = offer.Price;
}
}
In my view I use the model class as a List (List) and load the data like this:
var model = new viewModel();
#(Json.Serialize(Model.Offers)).forEach(function (item, index) {
model.offers.push({
name: item.name,
templateId: item.templateId,
contingent: ko.observable(item.contingent),
userOrderCount: ko.observable(item.userOrderCount),
price: item.price,
maximumOrder: item.maximumOrder
});
})
The viewModel is defined like this (shortend for readability):
function viewModel() {
var self = this;
self.offers = ko.observableArray();
}
Now after someone hits the mentioned update button I call this javascript function:
self.ConfirmOrder = function () {
var data = ko.toJSON(self.offers);
$('#overlay').css('display', 'block');
$.ajax({
type: 'post',
url: '/Snack/ConfirmOrder',
data: data,
contentType: 'application/json; charset=utf-8',
success: function (result) {
$('#overlay').css('display', 'none');
},
error: function (result) {
console.log(result);
$('#overlay').css('display', 'none');
}
});
}
Here you can see that I use the ko.toJSON method to convert the observableArray to a JSON String and use this string as the data argument for the ajax post.
The ConfirmOrder method in the MVC Controller looks like this currently:
[HttpPost]
public void ConfirmOrder(List<OrderSnackViewModel.Order> offers)
{
foreach (var item in offers)
{
_logger.LogInformation(item.Name);
}
}
There is no logic yet cause the offers list is created (so not null) but the count of list items is always 0.
In a concret example this is the JSON string I receive from the server while load the view:
[{"name":"Test","templateId":1,"price":1.94,"contingent":4,"maximumOrder":7,"userOrderCount":0},{"name":"Test 1","templateId":2,"price":1.50,"contingent":30,"maximumOrder":7,"userOrderCount":0}]
And this is the string i produce with the ajax call:
[{"name":"Test","templateId":1,"contingent":4,"userOrderCount":0,"price":1.94,"maximumOrder":7},{"name":"Test 1","templateId":2,"contingent":30,"userOrderCount":0,"price":1.5,"maximumOrder":7}]
What have I tried already:
I have tried to use FromBody in my MVC Controller
I have tried to prefix the JSON output with the name offer so my controller method can map the JSON string items to the object. (e.g. data = '{ "offers":' + data + '}'; )
I have tried to rename the Properties of my model to match exactly the JSON names. So I renamed Name to name and Contingent to contingent and so on.
I have tried to use an array instead of the List in the MVC controller action
Is there a master somewhere which can help me with this problem?
(If you need some more information please do not hesitate to ask)
Thanks to the input of #adiga I have found the solutions for (my) error.
[HttpPost]
public JsonResult ConfirmOrder([FromBody]List<Order> offers)
{
_logger.LogInformation("COUNT -> " + offers.Count());
foreach (var item in offers)
{
_logger.LogInformation(item.Name);
}
}
This is the working solution. I thought I already have tried it but maybe I have forgoten the content-type for the ajax post.
var data = ko.toJSON(self.offers);
$('#overlay').css('display', 'block');
$.ajax({
type: 'post',
url: '/Snack/ConfirmOrder',
data: data,
contentType: 'application/json; charset=utf-8',
success: function (result) {
//location.reload();
$('#overlay').css('display', 'none');
},
error: function (result) {
console.log(result);
$('#overlay').css('display', 'none');
}
});
Thanks again for all responses!

send multiple objects via ajax (using angular)

I have a list of user inputs in an object 'data'. (for e.g data.username, data.password, data.age)
i am passing the data object to backend like this using angular.
var submits = "=" + JSON.stringify(data);
$.ajax({
type: "POST",
url: serviceURL,
data: submits
});
I am passing two more objects. selections and grid. how can i pass all these three together in one ajax call ? or do i have to transfer it independently. will it affect the performance if i transfer these details separately.
can i do something like this to send the object together in one ajax call?
var data = {};
data[0] = data1;
data[1] = data2;
How can i retrieve it separately at the server side using c# if at all they are passed together.
Heres the 3 objects that i need to pass
data -->> ["Raul","New York","31"]
selections-->> ["dy.txt","my.txt","yy.txt"]
grid--> ["sesion","id"]
Assuming you have a view model like this in your server side
public class CreateUserViewModel
{
public string UserName{set;get;}
public string Location {set;get;}
public int Age {set;get;}
}
public class RegisterViewModel
{
public CreateUserViewModel User {set;get;}
public List<string> Selections {set;get;}
public List<string> Grid {set;get;}
}
and an MVC action method like this
public ActionResult Create(RegisterViewModel model)
{
// read model and save and return some JSON response
}
You can simply build the javascript object which matches the structure of the view model and post it using angualr's $http service. No need to worrry about setting content-Type or Json stringifying it. Angualr will take care of it.
var model={ User : {} ,Selections :[], Grid=[] };
model.User.Age =23;
model.User.UserName ="test";
model.User.Location="New York";
model.Selections.push("dy.txt");
model.Selections.push("some.txt");
model.Grid.push("session");
model.Grid.push("id");
var url="replcaeUrltoYourActionMethodHere";
$http.post(url, model)
.then(function(response)
{
// do something with the response
// var result= response.data
});
You can send multiple objects / variables in ajax with:
var submits = "=" + JSON.stringify(data);
$.ajax({
type: "POST",
url: serviceURL,
data: {submits : submits, data1:data1, data2:data2}
});
In your C# you can access data1 and 2 in the same way as you handle submits now.
Depending of what is in data1 and data2 you might need to stringify it first.
second option:
You can also if you want to (but it is more ugly) use the stringify on everything at once and only pass the string:
data = {};
data["data1"] = data1;
data["data2"] = data2;
var submits = "=" + JSON.stringify(data);
Are you using WebApi or MVC on the server? If so, the simplest approach would be to create a class which holds the 3 entities you need to send and leverage the built-in model-binding
So in your example you list what looks to be a user form, selections and grids. I'm not really sure what the last two are but an example Model might look something like this:
public class UserSubmissionViewModel
{
public UserSubmissionViewModel() { }
public UserFormModel User {get;set;}
public SelectionsModel Selections { get; set; }
public GridModel Grids { get; set; }
}
Then on your web api controller or your MVC controller you'd have a method such as this:
public async Task<IHttpActionResult> Submit(UserSubmissionViewModel model)
And your javascript would resemble something roughly like this:
var toSend = {"UserFormModel":data, "SelectionsModel":selections, "GridModel":grids};
$.ajax({
type:"POST",
data:toSend, //<--- you might need to JSON.stringify this, cant test this code at the moment
url:serviceURL //<-- Calls your Submit method on the controller
});

Call c# function from javascript function [duplicate]

I want to call CsharpFunction, a C# function in code-behind, from JavaScript. I tried the code below but whether the JavaScript condition is True or False, CsharpFunction was called regardless!
JavaScript code:
if (Javascriptcondition > 0) {
<%CsharpFunction();%>
}
C# code behind:
protected void CsharpFunction()
{
// Notification.show();
}
How do I call a C# function from JavaScript?
You can use a Web Method and Ajax:
<script type="text/javascript"> //Default.aspx
function DeleteKartItems() {
$.ajax({
type: "POST",
url: 'Default.aspx/DeleteItem',
data: "",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
$("#divResult").html("success");
},
error: function (e) {
$("#divResult").html("Something Wrong.");
}
});
}
</script>
[WebMethod] //Default.aspx.cs
public static void DeleteItem()
{
//Your Logic
}
.CS File
namespace Csharp
{
public void CsharpFunction()
{
//Code;
}
}
JS code:
function JSFunction() {
<%#ProjectName.Csharp.CsharpFunction()%> ;
}
Note :in JS Function when call your CS page function.... first name of project then name of name space of CS page then function name
A modern approach is to use ASP.NET Web API 2 (server-side) with jQuery Ajax (client-side).
Like page methods and ASMX web methods, Web API allows you to write C# code in ASP.NET which can be called from a browser or from anywhere, really!
Here is an example Web API controller, which exposes API methods allowing clients to retrieve details about 1 or all products (in the real world, products would likely be loaded from a database):
public class ProductsController : ApiController
{
Product[] products = new Product[]
{
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
};
[Route("api/products")]
[HttpGet]
public IEnumerable<Product> GetAllProducts()
{
return products;
}
[Route("api/product/{id}")]
[HttpGet]
public IHttpActionResult GetProduct(int id)
{
var product = products.FirstOrDefault((p) => p.Id == id);
if (product == null)
{
return NotFound();
}
return Ok(product);
}
}
The controller uses this example model class:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
Example jQuery Ajax call to get and iterate over a list of products:
$(document).ready(function () {
// Send an AJAX request
$.getJSON("/api/products")
.done(function (data) {
// On success, 'data' contains a list of products.
$.each(data, function (key, item) {
// Add a list item for the product.
$('<li>', { text: formatItem(item) }).appendTo($('#products'));
});
});
});
Not only does this allow you to easily create a modern Web API, you can if you need to get really professional and document it too, using ASP.NET Web API Help Pages and/or Swashbuckle.
Web API can be retro-fitted (added) to an existing ASP.NET Web Forms project. In that case you will need to add routing instructions into the Application_Start method in the file Global.asax:
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = System.Web.Http.RouteParameter.Optional }
);
Documentation
Tutorial: Getting Started with ASP.NET Web API 2 (C#)
Tutorial for those with legacy sites: Using Web API with ASP.NET Web Forms
MSDN: ASP.NET Web API 2
Use Blazor
http://learn-blazor.com/architecture/interop/
Here's the C#:
namespace BlazorDemo.Client
{
public static class MyCSharpFunctions
{
public static void CsharpFunction()
{
// Notification.show();
}
}
}
Then the Javascript:
const CsharpFunction = Blazor.platform.findMethod(
"BlazorDemo.Client",
"BlazorDemo.Client",
"MyCSharpFunctions",
"CsharpFunction"
);
if (Javascriptcondition > 0) {
Blazor.platform.callMethod(CsharpFunction, null)
}
Server-side functions are on the server-side, client-side functions reside on the client.
What you can do is you have to set hidden form variable and submit the form, then on page use Page_Load handler you can access value of variable and call the server method.
More info can be found here
and here
If you're meaning to make a server call from the client, you should use Ajax - look at something like Jquery and use $.Ajax() or $.getJson() to call the server function, depending on what kind of return you're after or action you want to execute.
You can't. Javascript runs client side, C# runs server side.
In fact, your server will run all the C# code, generating Javascript. The Javascript then, is run in the browser. As said in the comments, the compiler doesn't know Javascript.
To call the functionality on your server, you'll have to use techniques such as AJAX, as said in the other answers.

Posting/Binding multiple forms on backend ASP.NET MVC (MEF)

We are trying to send multiple forms with one Ajax (jQuery) Call to an ASP application.
We use the following jQuery code:
var formContainer = {
Form1 : form1.serialize(),
Form2 : form2.serialize()
}
$.ajax({
type: "POST",
url: '#Url.Action("CreateModel", "Controller")',
data: formContainer,
success: function (result) { }
});
On the server we receive the following in the Request.Form property:
Key : Value
Form1 : All serialized form elements for Form1
Form2 : All serialized form elements for Form2
Normally we use the following method so ASP is automaticly creating the object with the right property value:
public ActionResult CreateModel(ClassForForm1 obj)
But because the two forms are send together the modelbinder cannot bind and build the class.
So for this action we want the modelbuilder to use the values in Request.Form["Form1"].
We can't use a custom modelbinder, because we use an extern library (DevExpress ,they wrote an own implementation above this).
We are using the MEF framework to add functionalities (these functionalities are added as forms on the view). For this reason we do not know what too expect on the backend. So writing a wrapper ViewModel is not acceptable.
The functionality for proccessing the other forms data will be handeled inside other modules.
Any solutions are welcome!
Thanks in advance.
This is typically done using a combined view model. Otherwise, you would need to manually parse the request parameters. Here is a fiddle showing how to combine the data from multiple forms.
$(function() {
$('button').click(function(e) {
var form1 = $('#form1');
var form2 = $('#form2');
$.ajax({
type: "POST",
url: '/echo/html/',
data: form1.serialize()+"&"+form2.serialize(),
success: function (result) {
alert(result);
}
});
});
});
On the server, your view model would require:
public class IndexViewModel {
// properties from form1
public string first { get; set; }
// properties from form2
public string last { get; set; }
}
public class First {
public string first { get; set; }
}
public class Last {
public string last { get; set; }
}
And your action signature:
[HttpPost]
public ActionResult Index(IndexViewModel model) {
var firstModel = (new First()).CloneMatching(model);
var lastModel = (new Last()).CloneMatching(model);
return RedirectToAction("Thanks");
}
See Best way to clone properties of disparate objects for the CloneMatching extension method.
If you create you javascript object like this:
var formContainer = { obj : {
Form1 : form1.serialize(),
Form2 : form2.serialize()
}
}
The controller should match it up with the name 'obj' you created in the javascript with the 'obj' in your method....
public ActionResult CreateModel(ClassForForm1 obj)
My previous sample worked just because my class has name and value props. I'm realy sorry for that. But now you can see working DEMO
JS
function mapForm(form)
{
var result = {};
$.map($(form).serializeArray(),
function(el){
mapFormProperty(result, el);
});
return result;
}
function mapFormProperty(form, property)
{
form[property.name] = property.value;
}
$('.submit').click(function(){
var form1 = mapForm($('#form1'));
var form2 = mapForm($('#form2'));
var formContainer = {
'Form1': form1,
'Form2': form2};
$.ajax({
type: "POST",
url: '#Url.Action("CreateModel", "Controller")',
data: JSON.stringify(formContainer),
success: function (result) { }
});
Operations with forms and form container should give you next json string
"{"Form1":{"Prop1":"Value1","Prop2":"Value2"},"Form2":{"Prop1":"Value1","Prop2":"Value2"}}"
And your model binder will be able solve this, if you change your action signature
Action
public ActionResult CreateModel(ClassForForm1 Form1) //argument name must be equal to data property
//but not equal to class name
And it should work. it works in my test sample

Can't send javascript object array to new page

I have a javascript array of objects that I am trying to send to my new view. I don't want to use AJAX - this is a new page altogether. I can't seem to figure out how to send the array to my controller action.
I have an action that returns an UploadFile object to my view, which is added to an array in javascript. When the user tries to continue to "review" the results, I'm sending that array of objects to the new page.
public ActionResult Review(List<UploadFile> model)
{
return View();
}
I still tried using AJAX but I encountered two problems: 1) I want a new page, I don't want it to stay on the same page, 2) The model is still null.
$('.js_btn-review').click(function () {
$.ajax({
url: '/Document/Review',
data: documents,
type: 'GET'
});
});
I'm not sure how to do this - I know I've done it before, but I can't remember how I did it. I even tried setting an element and serializing:
$('.js_btn-review').click(function () {
$("#documents").val(documents);
$.ajax({
url: '/Document/Review',
data: $("#documents").serialize(),
type: 'GET'
});
});
What am I doing wrong here?
As you didn't state the structure of the js variable documents I am assuming it is just an array of UploadFiles. Something along the lines of:
var documents = [];
for (var i = 0; i < 10; i++) {
var d = {
id: i,
title: i.toString()
};
documents.push(d);
}
Which you then taking and sending via ajax. This will not work as documents do not have a container so the URL for the GET will look something like /Document/Review?undefined=&undefined=&undefined=&undefined=&
By changing it to
var data = {
model: documents
};
$('.js_btn-review').click(function () {
$.ajax({
url: '/Home/Review',
data: data,
type: 'GET'
});
});
The models should be populated.
As for the view changing you will need to do something other than .ajax as just goes and gets the response. it doesn't change pages.
The parameter name should be the same as the name of the data being sent, so if the data object is called documents, your parameter in the controller should have the same name as follows.
public ActionResult Review(List<UploadFile> documents)
{
return View();
}
the Javascript for that
$('.js_btn-review').click(function () {
$.ajax({
url: '/Document/Review',
data: JSON.stringify( documents ),
type: 'Post'
});
});
Without AJAX
It's just like the PRG Pattern so you POST a form.
#{
List<UploadFile> list = new List<UploadFile> { ... };
}
#using(Html.BeginForm("Review", "Controller", FormMethod.Post, new { }))
{
for (int i = 0; i < list.Count(); i++)
{
#Html.HiddenFor(m => list[i]);
}
<input type="submit" value="Review" />
}
Controller Actions
[HttpPost]
public ActionResult Review(List<UploadFile> list)
{
TempData["Review_list"] = list;
return RedirectToAction("Review");
}
[HttpGet]
public ActionResult Review()
{
var list = TempData["Review_list] as List<UploadFile>;
return View(list);
}
If you don't need to process the list on the server
Don't bother with passing back and keep the list in javascript:
Store it in Web Storage like sessionStorage as JSON
Do a regular GET to navigate to your new page (e.g. Review)
Retrieve the list from sessionStorage and build the html

Categories