Web API and C# out Values - c#

I have a service that contains a lot of functions with out parameters to return a few extra parameters.
I was wondering if it's possible to call a regular asp.NET web api service with out parameters and receive a value(in the form of out parameters, separate from the return value) from the service.
If it is possible, could you elaborate on what I need to do to achieve this?
Any help will be well appreciated.

No, this is not possible. The response from WebAPI will be a normal HTTP response with a body where the serialized returned data will be.
Of course, as usual, your response can be a complex object to serialize and you can include those out returns as members of it. For example:
public IHttpActionResult GetResponse(int id)
{
int outputInt;
string outputString;
YourMethodWithOutParameters(id, out outputInt, out outputString);
return Ok(new
{
Id = id,
OutputInt = outputInt,
OutputString = outputString,
});
}

Related

ASP.NET Web API object parameter not being filled on post request

I am trying to set up a small ASP.NET Web API projects so I can post data to the database from a small React.JS project. I tried alot of sollutions but the results made no sense and I have no idea how to fix it anymore.
I have this very simple model:
public class Hour
{
public int WeekID { get; set; }
}
And this is my controller
[HttpPost]
public IHttpActionResult AddHour(Hour hour)
{
return Ok();
}
This is the method that I use to POST my data
export const SaveWeek = weekData=> {
const headers = new Headers();
headers.append("Content-Type", "application/json");
const Week= {
method: "POST",
headers,
mode: "cors",
body: weekData
};
console.log("Hours:");
// Returns {"WeekID": 1}
console.log(Hours.body);
return axios.post("http://localhost:52350/api/REST/AddHour", {
Week
});
};
The way I call this SaveWeek method in React is:
// The JSON parameter is for testing hard coded to: {"WeekID": 1}
handleSave = async json => {
const data = await SaveWeek(json);
console.log(data);
this.closeModal();
};
I know that the axios POST request works, the way I tested that is by changing the method to not use any parameters and looking at the result that where received:
[HttpPost]
public IHttpActionResult AddHour(Hour hour)
{
// This returns a string in which the data that I sent
// can be found.
string body = Request.Content.ReadAsStringAsync().Result;
return Ok();
}
The weird thing is that the body will be filled with data when the method does not contain any parameters, but when I provide the method with the Hour object parameter the body will be an empty string (""). And also the Hour object parameter wont be filled with the values that I provide it.
What am I doing wrong here?
According to https://github.com/axios/axios#axiosposturl-data-config axios.post has following signature
axios.post(url[, data[, config]])
So you just need to change your request to
export const SaveWeek = weekData => {
//headers should be simple object, not Headers
const headers = {
"Content-Type": "application/json"
};
//removed body, because we pass data as second parameter
//removed method, because 'axios.post' implies using "post" method
const Config = {
headers,
mode: "cors"
};
const url = "http://localhost:52350/api/REST/AddHour";
return axios.post(url, weekData, Config);
}
An incoming request to the ASP.Net Web API pipeline is read as a forward-only stream for super speed. Once it has been read it cannot be read again.
[HttpPost]
public IHttpActionResult AddHour(Hour hour)
{
// With model binding
// use hour.WeekID
}
In this first example model binding is already done and once it has been read it cannot be read again. Hence, Request.Content will be empty after that.
[HttpPost]
public IHttpActionResult AddHour()
{
// Without model binding
// use Request.Content
}
In second example it does not use model binding therefore still has the Request.Content property populated.
Use one or the other, not both, do not mix with MVC model binding which works differently.
A better explanation is available in this blog post
http://www.hackered.co.uk/articles/asp-net-web-api-why-is-the-request-Content-empty-when-the-model-is-populated

Postman Testing send string to Web Api accepting string is null

I have been testing all the Get,Create,Update methods with Postman in which the Get passes in nothing. The Create and Update passes in raw json with Activity object with several properties that do match up with the C# class
So this signature for Create and Update works fine
[HttpPost]
public IHttpActionResult UpdateActivity(Activity activity)
Above works with Postman passing in JSON content type with all the properties. I have done this on OTHER projects.
HOWEVER
I'm trying to simply pass in a string and it is null no matter what
public IHttpActionResult DeleteActivity([FromBody]string Id)
{
// delete
var del = ActivityService.DeleteActivity(Id);
return Ok(del);
}
Postman I tried MANY ways
http://localhost:49810/api/activityapi/deleteactivity
I have tried MANY many ways based on blogs and google search one such example
{ "Id" = "5808786fa3e9ec79546b3c71" }
I know this is an older question but I wanted to help those who might have a similar problem as I was able to get this working.
In WebAPI Controller my method is setup as
[HttpPost]
public IHttpActionResult Create([FromBody] int eventId)
{
....
}
In order to get this to test properly in Postman you have to: In body, set to raw, make sure JSON (application/json) is set and then just add value like 2 that's it.. not like { "eventId":2 } which is proper JSON just the value and then it will work.
So in original poster's case, in Postman, if you set Body to raw, JSON (application/json) then "5808786fa3e9ec79546b3c71" as value it will work.
In Postman ensure the body is set to raw and select json and in the body just write "your string" in quotes. Do not use {} to surround it because that is to make a complex object
Try the following in the body, with the content-type as application/json
{ "5808786fa3e9ec79546b3c71" }
As when you specify it like so, it will attempt to de-serialize into a complex type with a property of Id
{ "Id" : "5808786fa3e9ec79546b3c71" }
Old question, but for those still wondering, I would recommend sending your string as a query parameter. Take a method like this for example:
[AllowAnonymous]
[HttpGet("resendEmailConfirmtionLink")]
public async Task<IActionResult> ResendEmailConfirmationLink(string email)
{
var user = await _userManager.FindByEmailAsync(email);
if (user == null) return Unauthorized();
var origin = Request.Headers["origin"];
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
token = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(token));
var verifyUrl = $"{origin}/verifyEmail?token={token}&email={user.Email}";
var message = $"<p>Please click the below link to verify your email address:</p><p><a href='{verifyUrl}'>Click to verify email</a></p>";
await _emailSender.SendEmailAsync(user.Email, "Please verify email", message);
return Ok("Email verification link resent");
}
This method expects a key value pair of a string called email. You can send your request like "http://localhost:5000/api/account/verifyEmail?email=myemail#test.com" or, in Postman, add it as a parameter like this:
postman query params
Your payload is not valid.
Change-->
{ "Id" = "5808786fa3e9ec79546b3c71" }
To-->
{ "Id" : "5808786fa3e9ec79546b3c71" }
[HttpPost]
public IHttpActionResult Create(int eventId)
{
....
}
Use form-data instead of raw-json
Key - eventId
Value - "5808786fa3e9ec79546b3c71"
This worked for me.

Getting POST data from WebAPI

We're working on developing an application that uses Plivo for sending and receiving SMS messages. For every request that Plivo sends, they also send a signature in the HTTP header so that we can verify the request came from Plivo and not from a random user.
https://www.plivo.com/docs/xml/request/#validation
To do this validation, we require the POST content as a query string (eg: To=15555555555&From=11234567890&TotalRate=0&Units=1&Text=Text!&TotalAmount=0&Type=sms&MessageUUID=2be622bc-79f8-11e6-8dc0-06435fceaad7).
Current solution
This is what we have so far:
private bool VerifyPlivo(object thing, HttpRequestMessage Request)
{
if (Request.Headers.Contains("X-Plivo-Signature"))
{
Dictionary<string, string> reqParams = (from x in thing.GetType().GetProperties() select x).ToDictionary(x => x.Name, x => (x.GetGetMethod().Invoke(thing, null) == null ? "" : x.GetGetMethod().Invoke(thing, null).ToString()));
IEnumerable<string> headerValues = Request.Headers.GetValues("X-Plivo-Signature");
string signature = headerValues.FirstOrDefault();
return XPlivoSignature.Verify(Request.RequestUri.ToString(), reqParams, signature, plivoToken);
}
else
{
return false;
}
}
[Route("RecieveSMS")]
[HttpPost]
public HttpResponseMessage RecieveSMS(PlivoRecieveSMS req)
{
if (!VerifyPlivo(req, Request))
{
return new HttpResponseMessage(HttpStatusCode.Forbidden);
}
... // do actual work here
}
This works by using the object that it maps to PlivoRecieveSMS and doing some reflection to get the properties and values, and sticking them in a Dictionary. This works well especially given our lack of the preferred solution...
Preferred solution
Right now, we require a model (PlivoRecieveSMS) to map the data, and then do introspection to find the key/values. We would like to move the logic to an extension of System.Web.Http.AuthorizeAttribute, so that we can do something as simple as:
[AuthorizedPlivoApi]
[Route("RecieveSMS")]
[HttpPost]
public HttpResponseMessage RecieveSMS(PlivoRecieveSMS req)
{
... // do actual work here
}
The actual authorization is done in AuthorizedPlivoApi - if it's not valid, the request never reaches the controller. But we cannot do this at the moment because we can't map it to a specific object inside of AuthorizedPlivoApi.
I would like to access the POST key's / values directly, or perhaps map it to a dynamic object that isn't pre-defined before hand. If I can do that, we can then achieve our preferred solution.
tl;dr: is there any way to push application/x-www-form-urlencoded data from a POST request into a Dictionary<string,string>() without using a specific model?

RESTful API return conventions

I'm still learning c# web API at the moment, and I've faced some problems.
so the code snippet below shows a portion of my codes that will create a new student in the database, what I am trying to do is to create the object and if it succeeded, it will return a HTTP-CREATED http response code and return the STUDENT OBJECT.
if it fails, it should return a HTTP-BADREQUEST response code and ALSO return the STUDENT OBJECT.
HOWEVER, in order to return the response code, I am unable to return a student object and vice-versa due to the return type set, hence, the dilemma.
// POST api/student
public HttpResponseMessage PostStudent(Models.Student student)
{
if (DBManager.createStudent(student) != null)
return new HttpResponseMessage(HttpStatusCode.Created);
// HOW TO RETURN STUDENT OBJECT?
else
return new HttpResponseMessage(HttpStatusCode.BadRequest);
// HOW TO RETURN STUDENT OBJECT?
}
The HttpRequestMessageExtensions.CreateResponse<T> Method has an optional formal paramater called value that can be used to create an HttpResponseMessage that contains both a status code and an object.
return Request.CreateResponse(HttpStatusCode.Created, student);
I'll tell you my own experience of building a web server for my company: DON'T use WebApi. There are so many limitations and in short, supports a very narrow usage scenario. Just stick to the traditional MVC controllers and life is much easier:
public ActionResult PostStudent(Models.Student s){
//do something
Response.StatusCode = 400;
return Json(s);
}

WCF UriTemplate with large query strings

I'm working with a rather large query string(~30+ parameters) and am trying to pass them to a WCF service I've setup.
I've run into a few issues specifically with the UriTemplate field. This service is setup to access a third party Api, so the query string may or may not contain all parameters. I'm curious if the best approach is to build a query string and pass that to the WCF service or to pass each parameter(and in some cases String.Empty) individually.
I've currently tried to dynamically build up a query string, however have hit a wall with either a 403 error when I try to pass the entire string( "?prm1=val&prm2=val" ) into the uritemplate of "ApiTool.jsp{query}", or I hit an invalid uritemplate response due to the fact I don't have name/value pairs listed.
I am pretty sure you'll need to list the parameters individually. Otherwise, UriTemplate will end up escaping things for you:
var ut = new UriTemplate("Api.jsp{query}");
var u = ut.BindByName(new Uri("http://localhost"), new Dictionary<string, string>() { { "query", "?param1=a&param2=b" } });
Console.WriteLine(u); // http://localhost/Api.jsp%3Fparam1=a&param2=b
You can 'unescape' querystring with IClientMessageInspector.
public class UriInspector: IClientMessageInspector
{
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
// change/replace request.Headers.To Uri object;
return null;
}
}
See MSDN how to add this to your Endpoint object.

Categories

Resources