POSTing object from AngularJS to .net WebAPI is always null - angularjs

I tried everything yet still when debugging the value at the web api post action is always null.
i tried changing the headers, i added [JsonObject(MemberSerialization.OptOut)] above the posted model class, i tried a simple Dto. nothing works...
this is the controller function that passes the user data:
$scope.Add = function () {
var user = {
ID: $scope.ID,
FirstName: $scope.FirstName,
LastName: $scope.LastName,
Age: $scope.Age,
Address: $scope.Address
};
$scope.usersRepo.push(user);
myService.addUser(user);
the service function is:
var addUser = function (user) {
return $http.post(
usersApi + '/addNewUser',
JSON.stringify(user)),
{
headers: {
'Content-Type': 'application/json'
}
};
};
and the web api action is:
[HttpPost, ActionName("addUser")]
public void Post([FromBody]UserModel value)
{
UsersDB.Add(value);
}
my model is this:
[JsonObject(MemberSerialization.OptOut)]
public class UserModel
{
public UserModel()
{
}
public UserModel(string firstName, string lastName, int age, string address)
{
this.Address = address;
this.Age = age;
this.FirstName = firstName;
this.LastName = lastName;
}
public void ConvertDto(UserDto userDto)
{
ID = userDto.ID;
FirstName = userDto.FirstName;
LastName = userDto.LastName;
Age = userDto.Age;
Address = userDto.Address;
}
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}

Use http post method like this. data should be your object to be passed without json stringify. I advised you to create a service for http methods.
var obj = {
url: your url,
async: true,
method: 'POST',
headers: {
"content-type": "application/json; charset=utf-8",
}
};
if (typeof data != 'undefined' && typeof data != null) {
obj.data = data;
}
$http(obj).then(function() {}, function() {});
Service :
// http methods
app.service('MethodProvider', ['$http', function ($http) {
var self = this;
self.get = function (url, data) {
var obj = {
url: url,
async: true,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
if (typeof data != 'undefined' && data != null) {
obj.params = data;
}
return $http(obj);
};
self.post = function (url, data) {
var obj = {
url: url,
async: true,
method: 'POST',
headers: {
"content-type": "application/json; charset=utf-8",
}
};
if (typeof data != 'undefined' && typeof data != null) {
obj.data = data;
}
return $http(obj);
};
self.put = function (url, data) {
var obj = {
url: url,
async: true,
method: 'PUT',
headers: {
'Content-Type': 'application/json'
}
};
if (typeof data != 'undefined' && data != null) {
obj.data = JSON.stringify(data);
}
return $http(obj);
};
self.delete = function (url) {
var obj = {
url: url,
async: true,
method: 'DELETE',
headers: {
'Content-Type': 'application/json'
}
};
if (typeof data != 'undefined' && data != null) {
obj.data = JSON.stringify(data);
}
return $http(obj);
};
}]);

Related

$http.post angularJS with files. ASP.NET

Try to use one of this example - Angularjs $http post file and form data
for example this
$scope.createPost = function () {
$http({
method: 'POST',
url: '/api/Blog/create-post/',
headers: {'Content-Type': 'multipart/form-data'},
data: {
Headline: $scope.Headline,
BodyText: $scope.BodyText,
ImgPost: $scope.fileAdress
},
transformRequest: function (data, headersGetter) {
var formData = new FormData();
angular.forEach(data, function (value, key) {
formData.append(key, value);
});
var headers = headersGetter();
delete headers['Content-Type'];
return formData;
}
})
.then(function onSuccess(response){
if(response.data = "Ok"){
$window.location.reload();
}
})
.catch(function onError(response) {
console.log("Error")
});
}
But I have an error in console (Internal Server Error) 500. I deleted header in my post request and it goes to api controller but with null parameters;
If I modify to this case shown below, but with out files it is working good.
$scope.createPost = function () {
$http({
method: 'POST',
url: '/api/Blog/create-post/',
data: {
Headline: $scope.Headline,
BodyText: $scope.BodyText,
},
})
.then(function onSuccess(response){
if(response.data = "Ok"){
$window.location.reload();
}
})
.catch(function onError(response) {
console.log("Error")
});
}
and I have this result
How I must modify my $http.Post that it will works with files?
My PostViewModel
public class PostViewModel
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[ScaffoldColumn(false)]
public string User { get; set; }
[StringLength(100, MinimumLength = 1)]
public string Headline { get; set; }
[StringLength(1000, MinimumLength = 1)]
public string BodyText { get; set; }
[ScaffoldColumn(false)]
public DateTime? Date_Time { get; set; }
public IList<IFormFile> ImgPost { get; set; }
public IList<int> fileAdress { get; set; }
}
First of all check if $scope.fileAdress is set to actual file. In $http call you can set Content-Type header to undefined before transformRequest
$http({
method: 'POST',
url: '/api/Blog/create-post/',
headers: {'Content-Type': undefined }, //set undefined here
data: {
Headline: $scope.Headline,
BodyText: $scope.BodyText,
ImgPost: $scope.fileAdress
},
transformRequest: function (data, headersGetter) {
var formData = new FormData();
angular.forEach(data, function (value, key) {
formData.append(key, value);
});
return formData;
}
})
Also you need to change action parameter attribute to [FromForm] or you can just remove it completely
[HttpPost]
[Route("create-post")]
public async Task<object> PostSaveOnFile(PostViewModel model)
This is enough to make it work. If you need to pass a single file consider updating your model to contain IFormFile instead of IList<IFormFile>
public class PostViewModel
{
//..
public IFormFile ImgPost { get; set; }
//..
}

Calling method using $http Post in AngularJS

I am trying to call the method ProcessCriteria in AngularJS below but for some reason I am keep getting error message:
VM18010:1 POST http://example.com/api/TalentPool/ProcessCriteria 404
(Not Found)
Below is my Calling code:
var param = { 'Item': item.Key, 'SolrLabel': SolrLabel };
$http({
method: 'POST',
url: '/api/TalentPool/ProcessCriteria',
data: param
//headers: {
// 'Content-Type': 'application/x-www-form-urlencoded'
//}
}).then(function (response) {
// success
console.log('Facet Data Posted');
return response;
},
function (response) { // optional
// failed
console.log('facet post error occured!');
});
And my Server side method:
[System.Web.Http.HttpPost]
public IHttpActionResult ProcessCriteria(string Item, string SolrLabel)
{
var itm = Item;
var solr = SolrLabel;
return Ok();
}
Any suggestions please?
ASP.net cannot match your request in its Route Table because you have 2 parameters in your action and the router doesn't understand it.
it expects a data object that your parameters warp to this.
First of all, make a Model like it:
public class Criteria
{
public string Item { get; set; }
public string SolrLabel { get; set; }
}
then change your action:
[System.Web.Http.HttpPost]
public IHttpActionResult ProcessCriteria(Criteria criteria)
{
var itm = criteria.Item;
var solr = criteria.SolrLabel;
return Ok();
}
Update
and update your javaScript part with JSON.stringify:
var param = { 'Item': item.Key, 'SolrLabel': SolrLabel };
$http({
method: 'POST',
url: '/api/TalentPool/ProcessCriteria',
data: JSON.stringify(param)
//headers: {
// 'Content-Type': 'application/x-www-form-urlencoded'
//}
}).then(function (response) {
// success
console.log('Facet Data Posted');
return response;
},
function (response) { // optional
// failed
console.log('facet post error occured!');
});
You can create a class as said by in above answer and you can pass data in http post like this
var obj = {
url: url,
async: true,
method: 'POST',
headers: {
"content-type": "application/json; charset=utf-8",
}
};
if (typeof data != 'undefined' || typeof data != null) {
obj.data = data;
}
$http(obj).then(function(response){
},function(error){
});
I got i working, below is the code for others if they get stuck on it.
var pvarrData = new Array();
pvarrData[0] = JSON.stringify(item.Key);
pvarrData[1] = JSON.stringify(SolrLabel);
pvarrData[2] = JSON.stringify($localStorage.message);
$http({
method: 'POST',
url: '/api/TalentPool/ProcessCriteria',
data: JSON.stringify(pvarrData),
headers: { 'Content-Type': 'application/json' }
}).then(function (response) {
// success
console.log('Facet Data Posted');
return response;
},
function (response) {
// failed
console.log('facet post error occured!');
});

What is causing the model to null

Angular Service:-
app.service('loginService', ['$http', function ($http) {
this.userLogin = function (user) {
console.log(user); //prints {'username': 'username#gmail.com', 'password': 123'}
$http(
{
url: "/api/user/login",
method: "POST",
data: { 'model': user },
contentType: "application/json"
})
.then(function (data) {
if (data.status.toLower() === "success") {
return data;
}
else {
return null;
}
});
}
Angular Controller
app.controller('homeCtrl', ['$scope', 'loginService', function ($scope, loginService) {
$scope.login = function (user) {
debugger;
console.log($scope.user);
var data = loginService.userLogin($scope.user);
}
}]);
WebAPI.
[Route("api/user/login")]
public void Post([FromBody]LoginVM model)
{
if(ModelState.IsValid)
{
}
else
{
}
}
But when I debug the WebAPI model it has all the values as null.
My LoginVM class
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
Why I am getting the properties as null?
Your passing your content type header incorrectly. It get's passed as part of the headers parameter like so:
$http({
url: "/api/user/login",
method: "POST",
data: { 'model': user },
headers: {
"Content-Type": "application/json"
}
}).then(function (data) {
if (data.status.toLower() === "success") {
return data;
} else {
return null;
}
});
However, unless you have changed the default headers you don't even need to pass the content type. See the default headers in the documentation.
So you can simply make your request like so:
$http({
url: "/api/user/login",
method: "POST",
data: {
model: user
}
}).then(function (data) {
if (data.status.toLower() === "success") {
return data;
} else {
return null;
}
});
And you shouldn't need the [FromBody] Attribute on your method because your LoginVM is a complex type (Class).
Also, I've had it in the past where sometimes visual studio plays up and it's not debugging correctly. It's worth closing visual studio and re-opening it if that's the IDE you're using.

Parameters on controller always null when submitted via Angular

I'm creating a js object with the same properties as my controller action expects as parameters.
controller.js
(function () {
'use strict';
angular
.module('app')
.controller('requestController', requestController);
requestController.$inject = ['$scope', 'lecturesFactory', 'attendeesFactory'];
$scope.setSelectedLectures = function () {
var lecture1, lecture2;
for (var i = $scope.lectures.length - 1; i >= 0; i--) {
var lecture = $scope.lectures[i];
if (lecture.selected === true) {
if (lecture1 == null) {
lecture1 = lecture.lectureId;
}
else {
lecture2 = lecture.lectureId;
}
}
}
attendeesFactory.setSelectedLectures($scope.emailAddress.text, lecture1, lecture2).then(function (data) {
$scope.showInvalidUserMessage = true;
$scope.message = data.message;
});
};
activate();
function activate() { }
}
})();
attendessFactory.js
(function () {
'use strict';
angular
.module('app')
.factory('attendeesFactory', attendeesFactory);
attendeesFactory.$inject = ['$http'];
function attendeesFactory($http) {
var service = {
setSelectedLectures: setSelectedLectures
};
return service;
function setSelectedLectures(emailAddress, lecture1, lecture2) {
var promise = $http({
method: 'POST',
url: '/Home/SetSelectedLectures',
data: {
emailAddress: emailAddress,
lecture1: lecture1,
lecture2: lecture2
}
}).then(function (response) {
console.log(response);
return response.data;
});
return promise;
}
}
})();
And my MVC Controller:
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult SetSelectedLectures(SelectedLectureData data)
{
// ...
}
}
public class SelectedLectureData
{
public String EmailAddress { get; set; }
public int Lecture1 { get; set; }
public int? Lecture2 { get; set; }
}
I've tried what some posts on StackOverflow suggested, such as using JSON.stringify, changing the content-type, but I still get the parameter values null (even if I put them directly in the action, instead of using a custom class).
Use [FromBody] anotation to make it working which will serialize data in SelectedLectureData model.
public IActionResult SetSelectedLectures([FromBody]SelectedLectureData data)
Otherwise you need to do
var promise = $http({
method: 'POST',
url: '/Home/SetSelectedLectures',
data: JSON.strigify({ "data": {
emailAddress: emailAddress,
lecture1: lecture1,
lecture2: lecture2
}})
})
Try updating your javascript to
function setSelectedLectures(emailAddress, lecture1, lecture2) {
var model = {
emailAddress: emailAddress,
lecture1: lecture1,
lecture2: lecture2
};
var data = JSON.strigify(model);
var promise = $http({
method: 'POST',
url: '/Home/SetSelectedLectures',
data: data
}).then(function (response) {
console.log(response);
return response.data;
});
return promise;
}
and using [FromBody] attribute on controller action
[HttpPost]
public IActionResult SetSelectedLectures([FromBody]SelectedLectureData data)
{
// ...
}
JSON property name should be same as class properties else it will take it as null
function setSelectedLectures(emailAddress, lecture1, lecture2) {
var promise = $http({
method: 'POST',
url: '/Home/SetSelectedLectures',
data: {
EmailAddress : emailAddress,
Lecture1: lecture1,
Lecture2: lecture2
}
}).then(function (response) {
console.log(response);
return response.data;
});

POSTing from Angular to .net WebAPI is always null

I am trying to Post an object from AngularJS to a MVC 5 WebApi Controller, but the value is always null
I can see in Chrome dev tools that the data can be found on the request.
Angular Controller:
$scope.join = function () {
if (!$scope.joinForm.$valid) return;
// Writing it to the server
var payload = $scope.user;
var res = $http.post('/api/some', JSON.stringify( { Data: { payload } }), { header: { 'Content-Type': 'application/json' } });
res.success(function (data, status, headers, config) {
$scope.message = data;
});
res.error(function (data, status, headers, config) {
alert("failure message: " + JSON.stringify({ data: data }));
});
}
MVC 5 API Controller:
public class SomeController : ApiController
{
// POST api/values
public void Post([FromBody]string value)
{
Trace.Write(value);
}
}
If I wrap my object in {Data: {payload}}
{"Data":{"payload":{"symbol":"xxx","amount":12000,"startdate":"2014-05-23T14:26:54.106Z","enddate":"2015-05-23T14:26:54.106Z","interval":"7 minutes"}}}
if I dont wrap it I get:
{"symbol":"xxx","amount":12000,"startdate":"2014-05-23T14:26:54.106Z","enddate":"2015-05-23T14:26:54.106Z","interval":"7 minutes"}
(Visual Studio 2015 is configured to use IISExpress)
Any ideas?
The reason value was null is because the framework's model binder was unable to match the parameter to the data that was sent in the body of the post.
Create a class to store your payload
public class User
{
public string symbol { get; set; }
public int amount { get; set; }
public DateTime startdate { get; set; }
public DateTime enddate { get; set; }
public string interval { get; set; }
}
update controller
public class SomeController : ApiController
{
// POST api/post
public void Post(User user)
{
//consume data
}
}
Angular controller
$scope.join = function () {
if (!$scope.joinForm.$valid) return;
// Writing it to the server
var res = $http.post('/api/some', $scope.user, { header: { 'Content-Type': 'application/json' } });
res.success(function (data, status, headers, config) {
$scope.message = data;
});
res.error(function (data, status, headers, config) {
alert("failure message: " + JSON.stringify({ data: data }));
});
}

Resources