How to pass HttpPostedFileBase from JavaScript as model instead of FormData - javascript

Is it possible to pass the form data with out using FormData by using the JavaScript Model. As my form has many controls I would like to go with Model approach instead of FormData.
Is there a way to pass selected files to controller with out using HttpPostedFileBase? I have nearly 10 different class which accepts HttpPostedFileBase
I have a class as follows in c#
public class ArtGallery{
Public string GallerName {get;set;}
Public HttpPostedFileBase[] Documents {get;set;}
}
The equivalent JavaScript Model is
class ArtGallery{
GallerName;
Documents[];
}
On my save of the form here is how I am doing it
function saveFormData(){
let gallery = new ArtGallery();
gallery.GallerName = "Test";
$.each($("input[type=file]"), function (i, obj) {
$.each(obj.files, function (j, file) {
gallery.Documents.push(file);
});
});
saveToDb();
}
function saveToDb() {
let url = "/MyController/PostData/";
$.ajax({
url: url,
type: 'POST',
async: false,
data: '{gallery : ' + JSON.stringify(gallery) + '}',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (result) {
},
error: function (request) {
}
});
}
My controller is as follows, which is getting triggered but documents I am unable to get
[HttpPost]
public JsonResult PostUserData(ArtGallery gallery) {
}

Related

Model vs List<Model> when sending post request to controller using Ajax

I have been trying to send a list model to controller using ajax but it seems it is not working at all
Model
public string MyModel {
public string myfieldName {get;set;}
}
controller
public JsonResult Create(List<myModel> list)
{
return Json("Success");
}
post request
$("body").on("click", "#btnSave", function () {
var list= new Array();
list = [{ myfieldName: 'ABC' }, { myfieldName: 'DEF' }];
//Send the JSON array to Controller using AJAX.
$.ajax({
type: "POST",
url: "/Project/Create",
data: JSON.stringify({ list }),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (r) {
alert(r + " record(s) inserted.");
}
});
});
so when I send this through, I check the browser and I can see that the request payload is sent with json object list
However when I go to controller the list is not binding it at all, so I check the http.context to check the request payload there and it all empty.
on the other hand when I change the controller like below
sending request with only model
public JsonResult Create(myModel data)
{
return Json("Success");
}
and change the js with below
$("body").on("click", "#btnSave", function () {
var data ={};
data.myfieldName= "test";
//Send the JSON array to Controller using AJAX.
$.ajax({
type: "POST",
url: "/Project/Create",
data: data,
success: function (r) {
alert(r + " record(s) inserted.");
}
});
});
the only difference here is that I don't send as json, so my question what is the is the difference between sending model vs a list of model using ajax
and what can I change to get the controller to bind the data or accept a list of model data
noting i'm using .Net core 2.0
Thank you
I usually use this method to send my Model as a List to my Controller method. I will try to show you regarding your scenario, how you can do this:
AJAX:
$("body").on("click", "#btnSave", function () {
var list= new Array();
list = [{ myfieldName: 'ABC'}, { myfieldName: 'DEF'}];
//Send the JSON array to Controller using AJAX.
$.ajax({
type: "POST",
url: "#Url.Action("Create","Project")",
data:{"json": JSON.stringify(list)},
dataType: "json",
success: function (r) {
alert(r + " record(s) inserted.");
}
});
});
And you can receive your Model like this in your Create method:
Make sure to import the System.Web.Script.Serialization namespace:
using System.Web.Script.Serialization
[HttpPost]
public JsonResult Create(string json)
{
var serializer = new JavaScriptSerializer();
dynamic jsondata = serializer.Deserialize(json, typeof(object));
List<string> myfieldName=new List<string>();
//Access your array now
foreach (var item in jsondata)
{
myfieldName.Add(item["myfieldName"]);
}
//Do something with the list here
return Json("Success");
}
Hope this helps you out.
Another method would be to utilize unobtrusive AJAX. All you would need is to install Microsoft jQuery unobtrusive AJAX from your Nuget Package Manager.
Then, in your view, call the following:
#{using (Ajax.BeginForm("Create", "ControllerName", null, new AjaxOptions()
{
HttpMethod = "POST",
// ...
}
}))
{
// Html code goes here
}
And also make sure that you include this at the bottom of your view:
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
Then, you can have a normal ActionResult setup (instead of JsonResult) for your controller and accept an argument of List list.

ajax post request with multiple paramaters

My controller:
[HttpPost]
public IActionResult UserRoleChanged(string roleName,string userName)
{
var a = roleName;
var b = userName;
return RedirectToAction("UserManager");
}
Script in view:
if (window.confirm('Are you sure that you want to change role?')) {
jQuery.ajax({
type: "POST",
url: "#Url.Action("UserRoleChanged", "DashBoard")",
dataType: 'json',
data: { 'roleName': this.text, 'userName': 'SomeName'},
cache: false,
success: function (data){
window.location.href = data;
},
failure: function (data) {
}
})};
When I run script above UserRoleChanged action does not invoke. If I try to remove userName variable from data in ajax then UserRoleChanged action method invokes without any problem. How can i pass multiple data to my controller? What is wrong with my code?
Remove the dataType: 'json' from the ajax, and try again. As you are trying to get the values on server side as normal variable, so dataType: 'json' is not required here.
You can create a model with same properties and pass it as a parameter. Its a good practice.
Looks like this.
public class User
{
public string RoleName { get; set; }
public string UserName { get; set; }
}
And the json looks like this example
{
"RoleName" : "somename",
"UserName" : "somename"
}

Pass an array as parameter to a controller from an ajax call in JavaScript

I'm working on an ASP.NET MVC 4 website and I've got some troubles with a functionality. I explain, I've to select entities displayed in a table with their linked checkbox :
Screenshot of my table where each row has a checkbox with the same Id as the entity
Console showing updates in the array
Inside my script I have been abled to store each checked Id's checkbox in an array and remove those if the checkbox is unchecked. But I can't pass the array to my controller's function to delete each selected entity in the database.
I used $.ajax() from jquery to send through a POST request the array (as JSON) but I always get 500 error :
JSON primitive invalid
Null reference
Here's my function in my script (I don't know if my array's format is valid) :
var sendDocsToDelete = function (docsArray) {
$.ajax({
type: 'POST',
url: 'Main/DeleteDocuments',
data: JSON.stringify(docsArray),
contentType: 'application/json; charset=utf-8',
datatype: 'json',
success: function (result) {
alert('Success ' + result.d);
},
error: function (result) {
alert('Fail ' + result.d);
}
});
}
Then, the POST call the following function in my controller :
[Authorize]
[WebMethod]
public void DeleteDocuments(string docsToDelete)
{
int id;
string[] arrayDocs = JsonConvert.DeserializeObject<string[]>(docsToDelete);
foreach (string docId in arrayDocs)
{
int.TryParse(docId, out id);
dal.DeleteDocument(id); // dal = DataAccessLayer is the class which interacts with the database by executing queries (select, delete, update...)
}
}
Update 2
[Authorize]
public ActionResult DeleteDocuments(int[] docsToDelete)
{
try{
foreach (string docId in arrayDocs)
{
int.TryParse(docId, out id);
dal.DeleteDocument(id); // dal = DataAccessLayer is the class which interacts with the database by executing queries (select, delete, update...)
}
return Json("Success");
}
catch
{
return Json("Error");
}
}
var sendDocsToDelete = function (docsArray) {
$.ajax({
type: 'POST',
url: 'Main/DeleteDocuments',
data: docsArray,
contentType: 'application/json; charset=utf-8',
datatype: 'json',
success: function (result) {
alert('Success ' + result.d);
},
error: function (result) {
alert('Fail ' + result.d);
}
});
}
Any ideas about this issue ? I hoped I was clear enough. Do not hesitate if you need more details.
If you are passing an integer array properly from $.ajax (i.e. your docsArray should be having value like [15,18,25,30,42,49]) then you should try :
[Authorize]
public ActionResult DeleteDocuments(int[] docsArray)
{
//int id;
//string[] arrayDocs = JsonConvert.DeserializeObject<string[]>(docsToDelete);
try {
foreach (int docId in docsArray)
{
//int.TryParse(docId, out id);
dal.DeleteDocument(docId); // dal = DataAccessLayer is the class which interacts with the database by executing queries (select, delete, update...)
}
return "Success ";
}
catch {
return "Error";
}
}
Update :
Your javascript code should be :
var sendDocsToDelete = function (docsArray) {
$.ajax({
type: 'POST',
url: 'Main/DeleteDocuments',
data: JSON.stringify(docsArray),
contentType: 'application/json; charset=utf-8',
datatype: 'json',
success: function (result) {
alert('Success ');
},
error: function (result) {
alert('Fail ');
}
});
}
Maybe the datatype in the JSON array is not a string? (This could happen if you have an array in the form of [45,64,34,6], or a mixed one like [345,"wef4"]).
To make sure something is a string in Javascript you can do this: var string = "".concat(otherVar);
Try changing your ajax data to something like this..
data : JSON.stringify({'docsToDelete':docsArray}),
Make these changes to your code.
In Jquery
data: docsArray, no need to stringify the array
In Controller
[Authorize] //remove [WebMethod]
public ActionResult DeleteDocuments(string[] docsToDelete) //Add ActionResult, Change parameter to accept array
{
int id;
string[] arrayDocs = docsToDelete; //no need of deserilization
foreach (string docId in arrayDocs)
{
int.TryParse(docId, out id);
dal.DeleteDocument(id); // dal = DataAccessLayer is the class which interacts with the database by executing queries (select, delete, update...)
}
return Json(id); //return id back to ajax call...
}

Sending a LIST of JSON object from javascript to MVC action

In my javascript i make a JSON like object with two properties : ControllerName and WordNumber and add them to an Array.
function TestN() {
var list = new Array();
$("*[wordNum]").each(function ()
{
var endRes = {
ControllerName: this.id,
WordNumber: this.getAttribute("wordNum")
};
list.push(endRes);
});
jQuery.ajax({
url:' #Url.Action("Translate")' ,
contentType: "application/json",
dataType: "json",
data: { List : JSON.stringify(list) }
,
traditional: true
})
}
</script>
In .net I've got this class with the same properties :
public class TranslateModel
{
public string ControllerName { get; set; }
public string WordNumber { get; set; }
}
And here is my action+
public ActionResult Translate(ICollection<TranslateModel> List)
{ return View(); }
As you may suppose the List property in Translate Action is empty (model binding doesn't work);
when you used JSON.stringify(list), it send string value to the controller action, instead of the object.
there are two approaches
1) either you send string to controller's action and Deserialize string to object and use.
2) create the model property as array of list and send that model to controller action without using JSON.stringify.
here are two links that may help you.
--approach-1
ASP.NET MVC 4 JSON Binding to the View Model - Nested object error
--approach-2
Passing json list to MVC 3
Try changing your AJAX function to this:
jQuery.ajax({
url: ' #Url.Action("Translate")',
type: 'POST',
contentType: "application/json",
dataType: "json",
data: JSON.stringify({ 'List': list }),
traditional: true
});

Convert JQuery ajax GET to POST

I have this jquery ajax get method on an Index razor in my application:
$.ajax({
url: "#Url.Action("SubmitProjectForPreapproval", "api/Project")",
type: "GET",
cache: false,
data: { projectId: "#ViewContext.RouteData.Values["ProjectId"]" }
}).done(function (data) {
var count = 0;
$.each(data, function (index, value) {
$("#ulMessages").append("<li>" + value + "</li>");
count++;
});
// Assume validation errors if more than 1 message
if (count > 1) {
$("#btnSubmit").removeAttr("disabled");
}
}).fail(function () {
$("#ulMessages").append("<li>An error occurred. Please try again later</li>");
$("#btnSubmit").removeAttr("disabled");
}).always(function () {
$("#imgAjaxLoader").hide();
});
This calls a method within the api/project controller that returns a list of strings:
[HttpGet]
public List<string> SubmitProjectForPreapproval(int projectId)
{ ... }
What I want to do is convert this to an ajax post method. I've been struggling to do just that for the better part of the day. My question is, what is everything that needs to change in order for this to happen? e.g. - change attribute of the method to [HttpPost], and how do I send it the route value? (int pojectId)
Edit: If I do this it works for some reason:
public List<string> SubmitProjectForPreapproval(/*int projectId*/)
{
int projectId = 3308;
...
}
Not sure why it doesn't find my method if I have the parameter there.
I'm not sure how the #Url stuff formats with your system - but just changing it to something like:
$.ajax({
url: "#Url.Action("SubmitProjectForPreapproval", "api/Project")",
type: "POST",
cache: false,
data: { projectId: "#ViewContext.RouteData.Values["ProjectId"]" }
}).done(function (data) {
If you're bit:
#Url.Action("SubmitProjectForPreapproval
..actually has any ?xxx values in it, you also need to add them into the data: { ... }
The problem was indeed the way I was sending the data to the controller action. I fixed it by doing the following:
Alter the ajax method (make use of JSON.stringify):
var projectIdObject = {
ProjectId: "#ViewContext.RouteData.Values["ProjectId"]",
}
$.ajax({
url: "#Url.Action("SubmitProjectForPreapproval", "api/Project")",
type: "POST",
cache: false,
data: JSON.stringify(projectIdObject),
contentType: 'application/json',
}).done(function (data) { ... }
Add a class to take this stringified value:
public class ProjectIdObject
{
public string ProjectId { get; set; }
}
Alter the controller action method to receive this new object and extract the value I want:
[HttpPost]
public List<string> SubmitProjectForPreapproval(ProjectIdObject projectIdObject)
{
int projectId = int.Parse(projectIdObject.ProjectId);
...
}

Categories