Passing AngularJS Model to Web API, Model is Null - asp.net-mvc

In need of some advice, I am trying to create a register/login section on a SPA project I am working on.
I am using AngularJS for the front end and MVC Web API for the back end.
Problem I am having is my model is showing as null when the Web API's POST method is hit.
Here is my code:
AngularJS Controller
SugarGlidersMain.controller('RegisterController', ['$scope', 'UserService', '$location', '$rootScope', 'FlashService', function ($scope,UserService, $location, $rootScope, FlashService) {
$scope.user = [{ID:'',Username:'',Password:'',Email:'',LastLogin:'',Role:'User', FirstName:'',LastName:''}]
$scope.register = function() {
var data = $scope.user;
UserService.Create($scope.user)
.then(function (response) {
if (response.success) {
FlashService.Success('Registration successful', true);
$location.path('/login');
} else {
FlashService.Error(response.message);
}
});
}
Note: Firstname, Lastname, Password and Email are bound to input fields in the html
AngularJS service
function Create(user) {
return $http.post('/api/User', user).then(handleSuccess, handleError('Error creating user'));
}
Note: user contains data when being sent to the Web API
WebAPI
// POST api/user
public void Post([FromBody]UserModel user)
{
string firstname = user.FirstName;
string lastname = user.LastName;
}
MVC Model
public class UserModel
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string Email { get; set; }
public DateTime? LastLogin { get; set; }
public string Role { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Does the data structure matter when passing a model to web API eg could I simply pass over Username, Email and Password without the other properties to the Web API and still use UserModel?
Thank you in advance.

In you current case you are passing $scope.user array to post but the thing is though you passed whole data in the array first element controller method won't understand that object, because its different than what actually the method is expecting. So for getting correct object on server you should pass correct JSON.
When you are passing object to API it should pass single user object rather than passing the whole array
UserService.Create($scope.user[0])
OR
Better change user object declaration to object
$scope.user = {ID:'',Username:'',Password:'',Email:'',LastLogin:'',Role:'User', FirstName:'',LastName:''};

Related

Slack API Slash Command sent to ASP.NET Core MVC Web App Issue

I am having an issue with my web api in ASP.NET Core MVC receiving the POST request from the Slack API when I attempt to execute a slash command. I do have the app hosted on a dedicated server (with a valid SSL Cert) and it is reachable by the Slack API.
Here is the method I am using to receive the POST request from the Slack API:
[HttpPost("slash/dispatch")]
[Consumes("application/x-www-form-urlencoded")]
public async Task<ActionResult<string>> ReceiveSlashDispatchEvent([FromForm] string data)
{
try
{
// string data;
// using (var sr = new StreamReader(Request.Body))
// {
// data = await sr.ReadToEndAsync();
// }
await _slackDispatchBotService.PostMessage(new SlackChatSendRequest
{
Channel = "XXXXXXX",
Message = data
});
}
catch (Exception e)
{
return Ok($"Error: {e.Message}");
}
return Ok();
}
Now if I don't declare anything in the method signature, it actually does enter it correctly. I have been successful in retrieving the request body using that commented section and directly reading in the Stream.
Here is a class definition that I have used in the method body previously (and it would fail each time):
public class SlackSlashDispatchEvent
{
public string Token { get; set; }
[JsonPropertyName("team_id")]
public string TeamId { get; set; }
[JsonPropertyName("team_domain")]
public string TeamDomain { get; set; }
[JsonPropertyName("enterprise_id")]
public string EnterpriseId { get; set; }
[JsonPropertyName("enterprise_name")]
public string EnterpriseName { get; set; }
[JsonPropertyName("channel_id")]
public string ChannelId { get; set; }
[JsonPropertyName("channel_name")]
public string ChannelName { get; set; }
[JsonPropertyName("user_id")]
public string UserId { get; set; }
[JsonPropertyName("user_name")]
public string UserName { get; set; }
public string Command { get; set; }
public string Text { get; set; }
[JsonPropertyName("response_url")]
public string ResponseUrl { get; set; }
[JsonPropertyName("trigger_id")]
public string TriggerId { get; set; }
}
I have also accessed the Request.QueryString field, which is always empty. Does anyone have a suggestion of where I should investigate further?
So far it seems to be that the framework I'm using is failing to successfully transform the request body data to whatever type I define in the method signature. Unfortunately, I'm having a hard time determining what the next troubleshooting steps are.
EDIT
While I have a strong feeling that there is a more graceful way to do this, I have implemented a solution. I do use the stream reader to grab the request body.
string data;
using (var sr = new StreamReader(Request.Body))
{
data = await sr.ReadToEndAsync();
}
I then wrote this method to parse the URLEncoded query parameters (that for some reason get sent in the request body from the Slack API) to convert it to my desired class:
public static SlackSlashDispatchEvent ParseQueryString(string queryString)
{
var dict = new Dictionary<string, string>();
var items = queryString.Split('&');
foreach (var item in items)
{
var keyValue = item.Split('=');
var key = HttpUtility.UrlDecode(keyValue[0]);
var value = HttpUtility.UrlDecode(keyValue[1]);
dict.Add(key, value);
}
var stringifyDict = JsonSerializer.Serialize(dict);
return JsonSerializer.Deserialize<SlackSlashDispatchEvent>(stringifyDict)!;
}
Serializing and then deserializing the Dictionary feels inefficient, but it's the best I could come up with for now.

Function gets null value from one of the parameters from ajax call

I want to send 2 parameters with data: using ajax. One of the params is a string, and that one always comes out on the c# side as it should, but the second parameter that is an object that consists of few strings and ints, always comes empty to the function.
$.ajax({
url : "/Clients/Create",
data: { client : client, country : country},
method : "post"
});
The interesting part is that when debugging the js file from browser, the debugger says that the objects contain all they should.
public void Create(Client client, string country)
{
//creates...
}
Country param comes out right, but all of the clients values are either null or 0. I tried swapping their places to see if it has something to do with order, no luck there. Also I tried multiple ways to do "data: { client : client, country : country},".
Client class:
public class Client
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public int Zip { get; set; }
public int CountryId { get; set; }
public Client() { }
}
This is how I'm building the object of a client in js.
var client = {
Name : name,
Address : address,
City : city,
Zip : zip
}
i suggest you if Client is a mvc model
var client = $.parseJSON('#Html.Raw(Json.Encode(yourModelClient))');
car country = "country";
var dataPlus = {
client : JSON.stringify(client),
country: country
};
ajax
$.ajax({
url: '#Url.Action("Create", "Client")',
data: dataPlus,
method : "POST",
});
then controller
[HttpPost]
public actionresult Create(Client client, string country)
{
}

Creating Parameter's for Api request in Alamofire.

I am using Xcode and swift 2 for creating a chat app for iOS platform. We are using asp.net mvc for creating the Api and mongodb as our database. Our SignUp model Contains Fields for Email and Password.
My Model is
public class SignUpViewModel
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string _id { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
And the Api method is
public JsonResult Sign_Up(SignUpViewModel signupviewmodel)
{
}
How can i pass and retrieve parameter's (data) as Model using Alamofire?

How to signup/login Parse User from authenticated Twitter oauth_token in .NET?

I've used the OAuth1Authenticator class from the Xamarin.Auth component library to allow users to login via Twitter. It authenticates correctly and gets me a response which has the following: oauth_token, oauth_token_secret, user_id, screen_name, oauth_consumer_key, oauth_consumer_secret.
Here is my code
OAuth1Authenticator twitterAuthenticator = new OAuth1Authenticator(Constants.Twitter.CONSUMER_KEY, Constants.Twitter.CONSUMER_SECRET, new Uri(Constants.Twitter.REQUEST_TOKEN_URL), new Uri(Constants.Twitter.AUTHORIZE_URL), new Uri(Constants.Twitter.ACCESS_TOKEN_URL), new Uri(Constants.Twitter.CALLBACK_URL));
twitterAuthenticator.Completed += async (sender, e) =>
{
if (!e.IsAuthenticated)
{
return;
}
string oauth_token = e.Account.Properties["oauth_token"].ToString();
The question is how do I then use that response to signup/signin a Parse User ? i.e. I want a ParseUser created on the parse database via the Twitter token and the session should be taken care of, same way it works for sign-via-Facebook using ParseFacebookUtils class
Problem is Parse doesn't support Login via Twitter in Xamarin, however, I believe parse does support any type of 3rd party authentication in an alternative way as shown below but I don't know how to do it.
Here are the most relative links
https://parse.com/tutorials/adding-third-party-authentication-to-your-web-app but the problem in this link is that it's made as a webpage button, don't know how to use that on a mobile, and it's for GitHub don't know how to use it for Twitter instead (Twitter is only OAuth1)
http://blog.parse.com/2013/12/03/bring-your-own-login/ This is exactly what I need but it needs a session Token, doesn't work with the oauth_tokens that twitter responds back to me, hence don't know how to use the method mentioned in the link
https://github.com/auth0/rules/blob/master/parse.md This looks like the solution, however I don't know how to use it, it does show the twitter icon so it should work with twtiter but how do I get that to work in .NET Update: I've found this xamarin component http://components.xamarin.com/view/Auth0Client which gets me closer to use the method mentioned in the first link in this paragraph, yet I'm still lost and don't know how to link autho0 to parse
All in all, I'm lost in this maze and really wish anyone could help me out.
I don't have a Twitter account so I can't test this but it looks like your POST DTO would be this:
public class TwitterAuthRequest
{
public AuthData authData { get; set; }
}
public class Twitter
{
public string id { get; set; }
public string screen_name { get; set; }
public string consumer_key { get; set; }
public string consumer_secret { get; set; }
public string auth_token { get; set; }
public string auth_token_secret { get; set; }
}
public class AuthData
{
public Twitter twitter { get; set; }
}
With a response DTO like this:
public class TwitterAuthResponse
{
public string username { get; set; }
public string createdAt { get; set; }
public string updatedAt { get; set; }
public string objectId { get; set; }
public string sessionToken { get; set; }
public AuthData authData { get; set; }
}
public class Twitter
{
public string id { get; set; }
public string screen_name { get; set; }
public string consumer_key { get; set; }
public string consumer_secret { get; set; }
public string auth_token { get; set; }
public string auth_token_secret { get; set; }
}
public class AuthData
{
public Twitter twitter { get; set; }
}
Don't forget to put in the headers:
("X-Parse-Application-Id", ApplicationId)
("X-Parse-REST-API-Key", ApplicationKey)
Source: https://parse.com/docs/rest#users
EDIT:
I have a created a draft for how you would use the DTO's:
public static class TwitterLoginProvider
{
public static Task<ServiceResponse<TwitterAuthResponse>> Login(
Twitter twitterInfo,
string applicationId,
string apiKey,
IRestClient restClient)
{
var request = new TwitterAuthRequest ()
{
authData = new AuthData ()
{
twitter = twitterInfo
}
};
restClient.AddHeader ("X-Parse-Application-Id", applicationId);
restClient.AddHeader ("X-Parse-REST-API-Key", apiKey);
return restClient.PostAsync<TwitterAuthResponse>("https://api.parse.com/1/users", request, Format.Json);
}
}
When you get the response from Xamarin.Auth, use that info to create a Twitter object and pass it to the IRestClient. As a response from the service you will get a response with the session information.
IRestClient interface: https://github.com/sami1971/SimplyMobile/blob/master/Core/SimplyMobile.Web/IRestClient.cs
Sample implementation: https://github.com/sami1971/SimplyMobile/blob/master/Core/SimplyMobile.Web/RestClient.cs
Alternatively you could use RestSharp: http://restsharp.org/

Passing form data to controller method - child properties are not getting filled in

My app is using JavascriptMVC on the client side, and ASP MVC is basically functioning only as a REST service. Here's a typical controller method:
public JsonResult Update(CustomerDto dto)
{
var repository = Factory.NewCustomerRepository())
// ... Convert DTO back to entity and save changes
return Json(dto);
}
The problem is, my CustomerDTO contains some properties that aren't getting converted from the form data into the objects that they should be. For example, PhoneNumbers:
public class CustomerDto
{
public int Id { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public PhoneNumberDto[] PhoneNumbers { get; set; }
// ... more properties
}
public class PhoneNumberDTO
{
public int Id { get; set; }
public int CustomerId { get; set; }
public string Label { get; set; }
public string Number { get; set; }
}
In the controller action, PhoneNumbers will have the correct number of elements in the array, but each object will have only null/default values. I've verified that the request is sending all of the appropriate form data:
Id 26
FirstName A
LastName Person
MiddleName Test
PhoneNumbers[0][CustomerID 26
PhoneNumbers[0][Id] 5
PhoneNumbers[0][Label] Mobile
PhoneNumbers[0][Number] (555)555-5555
PhoneNumbers[1][CustomerID 26
PhoneNumbers[1][Id] 8
PhoneNumbers[1][Label] Home
PhoneNumbers[1][Number] (654)654-6546
Any ideas on what could be going on? Am I just wrong in thinking that MVC3 can map nested objects from the form values automatically? Thanks for any help!
Actually the request should look like this if you want the default model binder to successfully bind those values (notice PhoneNumbers[0].CustomerID instead of PhoneNumbers[0][CustomerID]):
Id 26
FirstName A
LastName Person
MiddleName Test
PhoneNumbers[0].CustomerID 26
PhoneNumbers[0].Id 5
PhoneNumbers[0].Label Mobile
PhoneNumbers[0].Number (555)555-5555
PhoneNumbers[1].CustomerID 26
PhoneNumbers[1].Id 8
PhoneNumbers[1].Label Home
PhoneNumbers[1].Number (654)654-6546
You may take a look at the following blog post for the wire format used for collections.
As an alternative you could use JSON requests.

Resources