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)
{
}
Related
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.
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:''};
I'm fairly new to MVC web api, and trying to get POST requests to process properly. It's mostly working, but string values are HTML-encoded. I thought this would be handled automatically, and I find no way to do this manually.
Here is the ajax request:
$.ajax({
url: '/api/PulseStudies/UpdateTask',
type: 'POST',
data: { 'userID': userid, 'taskID': CurExamTaskID, 'comment': comment, 'complete': complete },
async: true,
...
Here is the server-side API:
[HttpPost]
public HttpResponseMessage UpdateTask(TaskResponse value)
{
Tasks.UpdateTask(value.userID, value.taskID, value.comment, value.complete);
return Request.CreateResponse(HttpStatusCode.NoContent);
}
public class TaskResponse
{
public int userID { get; set; }
public long taskID { get; set; }
public string comment { get; set; }
public bool complete { get; set; }
}
The comment value is HTML-encoded, e.g., "blah%20blah". How do I get a properly decoded value?
I believe you mean it is UrlEncoded. On the server side you want HttpServerUtility.UrlDecode() http://msdn.microsoft.com/en-us/library/6196h3wt(v=vs.110).aspx to get it back.
I am having troubles with my ajax call making it to my web.api method. If I remove the Guid orderId from both the api and the js, the call makes it to the controller, but the pizza object is empty. If I pass the Guid in the URL, it also makes it to the controller but no pizza. Please explain why this doesn't work or help me make it work.
JS:
var savePizza = function (orderId, pizza) {
var dataCall = $.ajax(config.savePizzaUrl, {
data: ko.toJSON({ orderId: orderId, pizza: pizza }),
type: "post",
contentType: "application/json"
});
return Q.when(dataCall);
};
Web Api:
[HttpPost]
public RequestReturn<Guid> SavePizza(Guid orderId, Pizza pizza)
{
return PizzaRequests.SavePizza(orderId, pizza);
}
JS Objects:
var pizza = function (data) {
this.Id = data.Id;
this.Size = new size(data.Size);
this.SizeId = data.SizeId;
this.Toppings = $.map(data.Toppings, function(item) {return new topping(item);});
};
var topping = function (data) {
this.Id = data.Id;
this.Name = data.Name;
this.Price = data.Price;
};
var size = function (data) {
this.Id = data.Id;
this.Name = data.Name;
this.Price = data.Price;
};
C# Objects:
public class Pizza
{
public Guid Id { get; set; }
public Guid SizeId { get; set; }
public Size Size { get; set; }
public IEnumerable<Topping> Toppings { get; set; }
}
public class Size
{
public Guid Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
public class Topping
{
public Guid Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
JSON Fiddler Post Capture:
ASP.NET Web API, by default, binds request body to a complex type (Pizza, in your case). Web API binds the body in its entirety to one parameter. Simple types such as GUID are bound from the URI path and query string. So, by passing GUID in the URI and posting only the JSON corresponding to pizza object (only the pizza and not anything else such as order ID), you can get this working.
In my experience the WEB API 2 HttpPost does not work if I try to put a Guid in the parameter collection. I have to put the Guid into the URI, e.g.
var url = window.applicationBaseUrl + "aiapps/"
+ GuidOrderId + "/DeleteByGroupId";
And then the ApiController like this
[HttpPost]
[Route("~/aiapps/{guid:Guid}/deletebygroupid")]
public AiAppsOpResult DeleteByGroupId(Guid guid)
{
Some have suggested that it will work to use a JSON object for the Guid that has an empty key, e.g. {'':OrderId} but not for me. And it does no good to declare the Guid parameter optional or nullable in the controller.
I have not tested #Badri's solution, but I think it will work. I do know the WEB API will work if I make a C# DTO that contains both the Pizza and the OrderIdGuid and POST that, e.g.
public class MetaPizza
{
public Pizza pizza {get;set;}
public Guid OrderId{get;set;}
}
and
[Route("~/api/postorder")]
[HttpPost]
public AiAppsOpResult CalcRisk(MetaPizza metaPizza)
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
url: window.applicationBaseUrl + "api/postorder" ,
data: _JSON_MetaPizza
})
Folks,
Can anyone help me or direct me to an example of a knockout viewmodel which contains an array of objects being passed to an asp.net mvc action? The only examples I have seen show just simple arrays of strings being passed.
Thanks
Here's an example from the official Knockout site. It's a Contacts editor build with nested arrays. [jsFiddle].
A fitting ASP.NET MVC Action could look like
public ActionResult SaveContacts(IEnumerable<Contact> contacts)
Where Contact is defined as the class:
public class Contact
{
public string firstName { get; set; }
public string lastName { get; set; }
public IEnumerable<Number> phones { get; set; }
}
Where Number is defined as the class:
public class Number
{
public string type { get; set; }
public string number { get; set; }
}
Given the JavaScript Knockout View Model from the example. Your save method could look like this
self.save = function() {
var jsonString = ko.mapping.toJSON(this.searchParams);
$.ajax({
url: "/MyController/SaveContacts",
data: jsonString,
type: 'POST',
contentType: 'application/json',
dataType: 'json'
});
};