Passing params from AngularJS to C# Controller - c#

I've tried researching this but I can't find anything anywhere that's helpful or any relevant answers.
For my angular controller I have:
app.controller('AdminCtrl', function ($scope, $http) {
$scope.data = {
Name: '',
Password: ''
},
$scope.login = function (data) {
$http({
method: 'POST',
url: '/login/postlogin',
data: JSON.stringify({
data: $scope.data
}),
contentType: "application/json",
dataType: "json"
}).success(function (data) {
alert('success!');
}).error(function (error) {
alert(error.message);
})
}
});
For my c# controller I have a very basic setup:
[HttpPost]
public string PostLogin(string data) {
return string.Empty;
}
My issue is that inside of the c# controller, data is always null. Does anyone know how to pass the name and password params over to the c# controller? I know for a fact that I am recieving values for them from my textboxes that I have. I am also recieving the success message/alert.Thanks!

Data is not a string. In c# make an object with Name and Password as properties and have this:
[HttpPost]
public string PostLogin(Data data) {
Edit in response to comment:
Yes you need to include the namespace that Data is in in your controller. You could try putting the Data object directly above.
public class Data
{
public string Name { get; set; }
public string Password { get; set; }
}
For clarity, data should not be stringified, instead just sent as data: data

Just send $scope.data directly, dont stringify it. Then modify your PostLogin method so it accepts two strings, one called Name and one called Password.

Related

I can't pass more than one parameter to ASP Web API

I tried to pass more than one parameter from client-side using jQuery to ASP Web API method, but the method can't accept that. I tried some of the solutions but the same thing.
Web API:
[HttpPost]
[ResponseType(typeof(Message))]
[Route("api/Messages/send-message")]
public async Task<IHttpActionResult> SendMessage(Email email, Message message){}
jQuery:
$.ajax({
url: '/api/Messages/send-message',
method: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({
email: EmailsArray,
title: $('#txtTitle').val(),
body: $('#txtContent').val(),
}),
success: function (response) {
console.log(response);
});
Error Message:
"message":"An error has occurred.","exceptionMessage":"Can't bind multiple parameters ('email' and 'message') to the request's content.","exceptionType":"System.InvalidOperationException"
If you're sending the data as JSON then all the data needs to be contained in a single coherent JSON structure. Having two separate input parameters on the server side does not fit with this concept.
In this situation you can create a DTO (Data Transfer Object) which is a class holding all of the items you want to transfer. Something like this:
public class EmailMessageDTO
{
public Email email { get; set; }
public Message message { get; set; }
}
Then you define the action method as accepting this single over-arching object
public async Task<IHttpActionResult> SendMessage(EmailMessageDTO dto) { }
And in the JavaScript:
data: JSON.stringify({
email: EmailsArray,
message: {
"title": $('#txtTitle').val(),
"body": $('#txtContent').val(),
}
}),
It's quite similar to the concept of having a ViewModel in MVC.
You need to add [FromBody] attribute to parameter and you need to make post data to application/x-www-form-urlencoded and you send only email parameter, you need to add message parameter if you wanna send title and body you need to create model like
model:
public class EmailSendModel(){
public string email{get;set;}
public string title{get;set;}
public string body{get;set;}
}
controller:
[HttpPost]
[ResponseType(typeof(Message))]
[Route("api/Messages/send-message")]
public async Task<IHttpActionResult> SendMessage([FromBody]EmailSendModel model){}

C# JSON deserialize removing '+'

I am using Newtonsoft.Json to deserialize a JSON object to a model. One of the strings in my object is:
mQvhIBYwGVtLQYtoSgUsHBxcvRcRiOpb94zqwYPF8Cz1scPia1pR4BgGZ2ThPv+NhXGlLFK/ZbHy/b3YzjKwBw==
I am finding that after RequestFolioDetailModel requestFolioDetailModel = JsonConvert.DeserializeObject(criteria); within the controller the value of User.SessionId is removing the '+' and saving the value with a space instead of the '+'.
Just to add this is a MVC Application. I do a Ajax call to the controller passing through a criteria and then serialise it into an object. See code snippets below:
Code
Javascript function:
function GetNotesForCustomer() {
var data = {
FolioId: gModel.SearchPageModel.Body.VfolFolioId,
User: {
SessionId: 'mQvhIBYwGVtLQYtoSgUsHBxcvRcRiOpb94zqwYPF8Cz1scPia1pR4BgGZ2ThPv+NhXGlLFK/ZbHy/b3YzjKwBw=='
},
Note: {
Voided: '0'
}
};
$.ajax({
url: gBaseUrl + 'Home/SearchCustomerNotes',
type: 'post',
cache: false,
async: true,
data: "criteria=" + JSON.stringify(data),
beforeSend: function () {
//Do Something
}, complete: function () {
//Do Something
},
error: function (result) {
//Do Something
},
success: function (result) {
//Do Something
}
});
}
Controller:
[Route("Home/SearchCustomerNotes/{criteria?}")]
public ActionResult SearchCustomerNotes(string criteria)
{
ActionResult actionResult;
RequestFolioDetailModel requestFolioDetailModel = JsonConvert.DeserializeObject<RequestFolioDetailModel>(criteria);
// do something with request Folio Detail Model
return actionResult;
}
Models:
public class RequestFolioDetailModel
{
public string FolioId {get; set;}
public RequestUserModel User {get; set;}
public RequestNoteModel Note {get; set;}
public RequestFolioDetailModel()
{
User = new RequestUserModel();
Note = new RequestNoteModel();
}
}
}
public class RequestUserModel
{
public string Login {get; set;}
public string Password {get; set;}
public string SessionId {get; set;}
public RequestUserModel()
{
Login = string.Empty;
Password = string.Empty;
SessionId = string.Empty;
}
}
How do I stop it from doing this as I need the + to stay in?
The problem is that you are passing your JSON from client to server as application/x-www-form-urlencoded content (the default content type for jQuery.ajax), but you are not URL encoding it.
The application/x-www-form-urlencoded content type requires the body of the request to contain URL encoded key-value pairs separated by & characters, just like in a URL query string. When the MVC server sees this content type, it applies a URL decode operation on each pair in the body, which will cause + characters to turn into spaces if the data is not properly encoded.
The quick fix, of course, is to encode your JSON string on the client side just after stringifying it:
$.ajax({
url: gBaseUrl + 'Home/SearchCustomerNotes',
type: 'post',
cache: false,
async: true,
data: "criteria=" + encodeURIComponent(JSON.stringify(data)),
...
});
However, since your data is actually JSON, a better solution is to actually send it as application/json content and take advantage of the built-in deserialization that the MVC framework provides. To do this, you need to make a couple of adjustments to your code on both client and server. On the client side, add a contentType specifier to your ajax call specifying the data is application/json. Then, remove the criteria= part from the data string. You do not need to do any URL encoding with this content type. Here is what the client side code would look like:
$.ajax({
url: gBaseUrl + 'Home/SearchCustomerNotes',
type: 'post',
cache: false,
async: true,
contentType: "application/json",
data: JSON.stringify(data),
...
});
On the server side, change your method to accept a RequestFolioDetailModel object directly. You can remove the DeserializeObject call from the body of the method, since the MVC framework will take care of deserializing the object for you. And of course, you need to adjust your Route attribute to remove the criteria part. You may also want to add HttpPost to it while you're at it.
[HttpPost, Route("Home/SearchCustomerNotes")]
public ActionResult SearchCustomerNotes(RequestFolioDetailModel requestFolioDetailModel)
{
// do something with request Folio Detail Model
...
}

How do I create a model using AJAX in ASP.NET MVC 5

Currently I can to create models regularly (by going SettingProfile/Create)
But when I try to use AJAX to send data wrapped in settingProfile JS object it returns HTTP 500 Internal Server Error error, I believe problem is in the data type. What would be correct way of calling Create method in AJAX?
My code:
Model:
public class SettingProfile
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string Name { get; set; }
public long? UserId { get; set; }
public string Url { get; set; }
}
View (JS):
function saveSettingProfile() {
var name = prompt("Please enter profile name", "");
var url = $("form").serialize(); // Not AJAX url, its a variable in model
var settingProfile = {
Name: name,
Url: url
};
jQuery.ajax({
url: "#Url.Action("Create", "SettingProfile")",
contentType: "application/json; charset=utf-8",
dataType: "json",
method: "POST",
data: settingProfile
}).done(function (response) {
alert("Profile saved successfully");
}).fail(function () {
alert("Could not save profile");
});
}
Controller:
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Name,Url")] SettingProfile settingProfile)
{
settingProfile.UserId = 8; // TODO: get user id from session
if (ModelState.IsValid)
{
db.SettingProfiles.Add(settingProfile);
db.SaveChanges();
return Json(new { success = true });
}
return Json(new { success = false });
}
500 error means, your server code is crashing. It could be of many reasons. One thing i noticed (which might cause a 500 error) is the way you are sending data.
You specified the contentType as "application/json" .But you are sending the javascript object as it is. So your request payload will be sent as something like
Name=SomeNameValue&Url=SomeUrlValue And with your current server code, the model binder cannot map it to an object of SettingProfile.
The solution is to send the stringified version of your javascript object. You may use the JSON.stringify method to do so.
jQuery.ajax({
url: "#Url.Action("Create", "SettingProfile")",
contentType: "application/json; charset=utf-8",
method: "POST",
data: JSON.stringify(settingProfile)
}).done(function (response) {
alert("Profile saved successfully");
};
Now your client code will send a request payload like
{"Name":"SomeName","Url":"SomeUrl"}
and model binder will be able to map it properly.
If it is simple data, you can simply not mention a custom contentType and send the js object as it is. jQuery will use the default contentType value which is "application/x-www-form-urlencoded" and model binding will work.
So the below code will work fine.
jQuery.ajax({
url: "#Url.Action("Create", "SettingProfile")",
method: "POST",
data:settingProfile
})
You may also check the browser's network tab and see the response coming back from the server for that ajax call. If an exception happens, you can see the details there.

POSTed JSON object ending up with default values in API controller

I'm trying to POST some data to my web API using jQuery's AJAX function, but MVC doesn't serialise it successfully on the other end - it simply leaves the default values for the model. Some seemingly useful answers don't seem to solve my problem, and its not at all complicated, so I'm not sure what's going wrong.
My model:
public class SavedLevel
{
public int ID { get; set; }
public string Data { get; set; }
}
AJAX request:
var postData= {};
postData.ID = 12;
postData.Data = "hello";
$.ajax(
{
url: "api/level/post",
type: "POST",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({data : postData}),
dataType: "json",
success: function (data)
{
//Something
},
error: function (jqXHR, textStatus, errorThrown)
{
//Something
}
});
The API controller.
[Route("api/level/post")]
[HttpPost]
public HttpResponseMessage PostLevel(SavedLevel data)
{
Debug.WriteLine("id : " + data.ID);
Debug.WriteLine("data : " + data.Data);
return new HttpResponseMessage(HttpStatusCode.OK);
}
The request body.
{"data":{"ID":12,"Data":"hello"}}
The Debug console outputs 0 and "" instead of the expected 12 and "hello".
Thanks for reading.
Note: I tried using a dynamic object and doesn't work at all - I can't even check if it's null.
Change your data to:
data: JSON.stringify(postData),
So the request body becomes:
{"ID":12,"Data":"hello"}
The C# is expecting the SavedLevel object, but you are sending the object wrapped in another object.

Having trouble passing Javascript array of objects to MVC3 controller, works with WCF service, any ideas?

I am having problems passing a javascript array to an MVC3 controller, not sure what I am doing wrong but this code does work with standard WCF service.
$(function () {
$("button").click(function () {
Poster();
});
});
function Poster() {
var data = [];
data.push(new WidgetProperty("test1", "value1"));
alert(data.length);
$.post("Home/Test", {test : data});
}
function WidgetProperty(name, value) {
this.Name = name;
this.Value = value;
}
and controller is
[HttpPost]
public ActionResult Test(WidgetProperty[] test)
{
return View("About");
}
public class WidgetProperty
{
public string Name { get; set; }
public string Value { get; set; }
}
Any ideas why the object that comes to the controller has null values for the properties? Checked with fiddler and it appears it passing the correct values.
Thanks!
You should use JSON.stringify() on your data before you post it, and since you know the data type is JSON, it is best to specify that the data being posted is JSON.
$.post("Home/Test", {test : JSON.stringify(data) }, "json");
Live DEMO
Edit:
I researched this a little more and it seems that you need to include contentType: "application/json" in order for this to work in mvc3:
$.ajax({
type: "POST",
url: "Home/Test",
data: JSON.stringify(data),
success: function(data){},
dataType: "json",
contentType: "application/json"
});

Categories