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
Related
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!
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
});
I am building an ASP.NET MVC application It currently has a button that once clicked does an Ajax call to the controller as so:
function getData() {
$.ajax({
url: "/Home/GetData/",
type: "POST",
contentType: 'application/json',
success: function (data){
//need to do stuff here
}
});
}
The controller then initializes a class, converts it to XML and then converts that to the following dictionary (There is a reason for this):
public ActionResult GetData()
{
List<People> peeps = GetPeeps();
string xml = ToXml(peeps);
Dictionary<string,List<string>> stuff = ToDictionary(xml);
return Json(stuff);
}
I would like to be able to 'Do stuff' with this data client side with javascript.
The APIs I have to work with Server side return XML data.
The APIs I have to work with Client side require string arrays. (Hence the conversions)
Is there a way to use the dictionary i've defined above client side? Could someone perhaps expand from this (if possible) to add to the ajax call a small method that prints the contents of the dictionary to a message box? just to give me a starting point from how to use the dictionary in javascript.
Thanks in advance
You can try in the ajax call as follow:
function getData() {
$.ajax({
url: "/Home/GetData/",
type: "POST",
contentType: 'application/json',
success: function (data){
console.log(data.key1); // value for key1
//or to list all values
for(var key in data){
console.log(data[key]);
}
}
});
}
Controller (for explanation purposes):
public ActionResult GetData()
{
//List<People> peeps = GetPeeps();
//string xml = ToXml(peeps);
//Dictionary<string,List<string>> stuff = ToDictionary(xml);
Dictionary<string,List<string>> stuff = new Dictionary<string, List<string>>
{
{"key1", new List<string> {"a", "b", "c"}},
{"key2", new List<string> {"d", "e", "f"}},
};
return Json(stuff);
}
I hope this is clear enough. Let me know how you go :)
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.
I am developing a web site using MVC 3 razor, in which I have the following situation:
A controller method:
public ActionResult MyControllerMethod(int parameter){
''go to bd a do some staff
IList<My_Custom> datafromDB = MyService.GetData(parameter);
'returns to my string tuped view
return View(datafromDB );
}
A strong typed view in which I use JavaScript:
#model IList<My_Custom>
<script type="text/javascript">
function getData()
{
var parameter = document.getElementById('myParamater').value;
$.get('/MyController/MyControllerMethod/' + parameter, function (data) {
loadData();
}
);
}
function loadData()
{
clearData();
datos = #Html.Raw(Json.Encode(Model));
//do some stuff with datos
}
</script>
The JavaScript call to the controller works fine but my problem is that the string typed view seems like is not taking the new value for the #model, so keeps loading the same information.
Although I have debugged the action controller and it returns different data every time.
So is there any way to refresh the Model value of a string typed view?
I also tried to process the data value of that line
$.get('/MyController/MyControllerMethod/' + parameter, function (data) {
but I wasn't successful doing that.
Your action return view, that's why nothing works. How your code works:
Load data in action, then generate view with json on the page
Send requst to the server and receive html with json (all this data are in memory),
then you access json from first step
How it must work:
Create view
Send request to the server (another method, that returning Json)
Access data
public ActionResult YourJsonAction(int parameter)
{
IList datafromDB = MyService.GetData(parameter);
return Json(datafromDB, JsonRequestBehavior.AllowGet);
}
function getData()
{
var parameter = $('#myParamater').val();
$.get('/MyController/YourJsonAction/' + parameter, function (data) {
//data from YourJsonAction
});
}