I have an AngularJS app that has to post data to a 3rd party URL. To get around the CORS browser issue, I am posting the data to my .net controller which will then post it to the 3rd party URL. In my javascript file, I've built the query string I want to pass to the 3rd party URL. Here is my code that posts to my .net controller:
var parms = "name=john&phone=1234567890&sex=male";
return $http({
url: '/UserForm/PostData/',
method: "POST",
data: parms
});
My c# controller:
[HttpPost]
public string PostData(String parms)
{
return "";
}
the parms variable in PostData is null. What do I need to do to pass my querystring string to my controller?
Can you try this? First - why don't you just define all parameters inside the controller post request definition? Second - I guess you have an error in your URL, you don't need the slash after "/UserForm/PostData" (If you don't use some custom routing in your MVC of course)
$http.post("/UserForm/PostData", { name: "john", phone: "1234567890", sex: "male" }).then(blahblahal....;
+
[HttpPost]
public string PostData(String name, String phone, String sex)
{
return "";
}
If this is for a WebApi controller, instead of trying to read parms as a parameter passed to the action, use ReadAsString to read the posted data. In your example the result should be the same value in your parms variable.
[HttpPost]
public IHttpActionResult PostData()
{
var parms = Request.Content.ReadAsStringAsync().Result;
// Submit parms to third-party api.
return Ok();
}
This task is more appropriate for WebApi, but if you need to use an MVC controller, you can read what was posted by reading Request.InputStream:
public ActionResult PostData()
{
string parms;
using (var sr = new System.IO.StreamReader(Request.InputStream))
{
parms = sr.ReadToEnd();
}
// Submit parms to third-party api.
return new EmptyResult();
}
You can try this.
[HttpPost]
public string PostData(System.Net.Http.Formatting.FormDataCollection form)
{
string name=form.get("name");
string phone=form.get("phone");
string sex=form.get("sex");
}
Or else you can try this solution too, you just need to add couple of lines.
public class PersonData
{
public string name { get; set; }
public string phone { get; set; }
public string sex { get; set; }
}
[HttpPost]
public string PostData([FromBody]PersonData form)
{
string name=form.name;
string phone=form.phone
string sex=form.sex;
}
Related
Is there any way to call an API to know its required parameters?
for example, if there is a controller has a method takes a name and date as a parameters
[HttpPost]
public string testUrl(string name,string date)
{
return "success";
}
now what I am trying to do is to make a dynamic form take an API URL and generate all required inputs so I have to find some way to call the URL and return the required parameters.
The quick and dirty way would be to just hard code it:
[HttpPost]
public string testUrl(string name,string date)
{
return "success";
}
public APISchema TestUrlSchema(){
return new APISchema() {
Parameters = new List<Parameter>(){
new Parameter(){ Name = "name", Type = "String" },
new Parameter(){ Name = "date", Type = "String" }
}
};
}
public class APISchema {
public List<Parameter> Parameters {get;set;}
}
public class Parameter {
public String Name {get;set;}
public String Type {get;set;}
}
You could use Reflection to auto-generate this if you want to do it for a large number of actions.
As comments have mentioned, there are libraries Swagger which will do this for you.
I need to send a date like
2007/08/01 00:00
as one of the values in my AXIOS GET
https://restapi.azurewebsites.net/api/PublicationReport/" +
dbid +
"/" +
sortDate
As you can tell it plays havoc with the Web API controller
<Route("api/PublicationReport/{dbid}/{sortDate}")>
The controller thinks that every "/" is a new parameter.
Is there a special format that must be used or do I need to send it as a json object?
I went with
params: {
dbid: dbid,
sortDate: sortDate
},
on the client side and below for the server side
Public Function GetValues(dbid As Integer, sortDate As String) As String
You can just create an object like this:
public class SomeQuery
{
public string SomeParameter { get; set; }
public int? SomeParameter2 { get; set; }
}
And then in controller just make something like that:
[HttpGet]
public IActionResult FindSomething([FromQuery] SomeQuery query)
{
// Your implementation goes here..
//then you can access query value using HttpContext.Request.Query
}
or using method params
[HttpGet]
public IActionResult FindSomething(string value1, string value2)
This is related to my previous question.
I'm wondering, can I pass a JS array the same way (as the accepted answer in previous question) even if now I'm trying to send a bit more complex array:
If yes, then how? Getting nulls while receiving in controller.
this is my model:
public class QuestionModel
{
public bool Choice { get; set; }
public List<object> ChoiceQuestions { get; set; } //can i use List<object>?
public int Id { get; set; }
public string Question { get; set; }
public bool Short { get; set; }
public object ShortQuestion { get; set; } //here aswell - can I use object?
public string Type { get; set; }
}
Not even sure if I can reuse the js code for sending the data to controller that was given in the answer. If no, then how should I solve this? Still I have to be able to send the data via post to controller, and then after processing data return it back to the view.
You may make Json of any object as a single hidden form field and then post the form to action with string parameter. Then on server side desterilize json to the object inside the action method - even in another controller. You may return different view from the controller method.
Javascript (Say on Stock Page/View)
var form = document.createElement("form");
var input = document.createElement("input");
input.setAttribute("type", "hidden") ;
input.setAttribute("name", "outwardStocks") ;
input.setAttribute("value", JSON.stringify(selectedrecords));
form.appendChild(input);
document.body.appendChild(form);
form.action = "/CRM/Invoice/Index";
form.method = "post"
form.submit();
Controller code (Say Invoice Controller)
[HttpPost]
public IActionResult Index(string outwardStocks)
{
InvoiceItems invItems = JsonSerializer.Deserialize<InvoiceItems>(outwardStocks);
......
return View("Invoice" InvoiceVM);
}
In javascript I am making an ajax post request to one of my JAX-RS functions like this
var postPackingListRequest = $http({
method: "post",
url: "/rest/v1/submit",
data: $scope.items
});
And now in my JAX-RS method I am trying to get the varibale $scope.items that was passed. I know I can get path params in the path like this
public Response getPathParams(#QueryParam("id") int id) {
But how can I get the data, which is passed in the body?
Thanks
EDIT
#POST
#Path("submit")
#Consumes(MediaType.APPLICATION_JSON)
#ApiResponses({ #ApiResponse(code = 201, response = Response.class) })
#Produces("application/json")
public Response submitPackingList(TestUser testUser) {
}
public class TestUser {
public String id;
public String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
When I send a request to this with the TestUser there I am getting a HTTP 400 error. Here is how I am sending it
var postPackingListRequest = $http({
method: "post",
url: "/rest/v1/submit",
data: "{'user':'1', 'name':james}"
});
Lets say your method is supposed to handle GET request like below
#GET
public Response getPathParams(#QueryParam("id") int id)
Now in the above method every argument must be annotated with something. In your case it is QueryParam. It may be PathParam and several others as well.
Only one argument is allowed which is not annoatated in JAX-RS.
Let's say you have User object like below:
public class User{
String userName;
int userId;
//getters and setters
}
and you want to accept user details that are coming via body of request then your method signature would look like below:
#GET
public Response getPathParams(#QueryParam("id") int id, User user)
Depending upon what the above method consumes whether it be json or xml the request body will be converted to User object and will get bind to your argument.
In case you are using Json you will need explicit MessageBodyReader for it.
I have a custom javascript on the client side that I use to build up a querystring and pass over to my asp.net-mvc controller
var templateQueryString = BuildTemplate();
$.ajax({
url: '/MyController/Save?' + templateQueryString,
type: 'post',
dataType: 'json',
success: function (data) {
}
}
and on my controller all of the properties leverage the model binding so it comes in as a single object on the server side. NOTE: that this is a pretty complex object with arrays and arrays of sub objects:
public ActionResult Save(MyTemplate template)
{
}
the issue now is that I need to be able to convert from my C# object back to a string that represents "myTemplateQueryString" on the client side.
Is there any recommended way to take an object and do the "reverse" model binding. They key here is that it generates a string that I could use as a query string again in the future to pass into another asp.ent-mvc controller action.
Here is an example of the querystring that I am storing locally:
<input type="hidden" value="showIds=false&showRisks=false&
amp;statusIds=2&statusIds=1&statusIds=6&statusIds=8&
amp;statusIds=3&statusIds=9&showCompleted=0"
name="filterQueryString" id="filterQueryString">
As #haim770 said it would be easier if you used JSON in the request payload, and not the query string to pass your complex object to the server.
Regarding creating the query string from a model there is not a built-in method that does something like that or any recommended approach as far as i know. An obvious solution is to use reflection and build the query string from your properties.
Assuming your BuildTemplate class looks something like:
public class BuildTemplate
{
public bool ShowIds { get; set; }
public bool ShowRisks { get; set; }
public bool ShowCompleted { get; set; }
public int[] StatusIds { get; set; }
}
You can develop an extension method to convert any object to a QueryString. Here is some initial code you can start with:
public static class ObjectExtensions
{
public static string ToQueryString(this Object obj)
{
var keyPairs = obj.GetType().GetProperties().Select(p =>
new KeyValuePair<string, object>(p.Name.ToLower(), p.GetValue(obj, null)));
var arr = new List<string>();
foreach (var item in keyPairs)
{
if (item.Value is IEnumerable && !(item.Value is String))
{
foreach (var arrayItem in (item.Value as IEnumerable))
{
arr.Add(String.Format("{0}={1}", item.Key, arrayItem.ToString().ToLower()));
}
}
else
arr.Add(String.Format("{0}={1}", item.Key, item.Value.ToString().ToLower()));
}
return "?" + String.Join("&", arr);
}
}
Then you can easily invoke this code on any object to generate a query string:
var person = new BuildTemplate() { StatusIds = new []{ 1, 5, 8, 9 }, ShowRisks = true };
var queryString = person.ToQueryString();
This would generate a query string like:
"?showids=false&showrisks=true&showcompleted=false&statusids=1&statusids=5&statusids=8&statusids=9"
This query string should work just fine with the default model binder for the BuildTemplate class.