How can I test my asp.net web API method? - asp.net-web-api

I have a web api method:
[HttpPost, ActionName("GET")]
public string Get(string apiKey, DateTime start, DateTime end)
{
var user = db.Users.SingleOrDefault(u => u.Id == apiKey);
if (user == null)
{
return string.Empty;
}
var records = db.Histories.Where(h => h.Date >= start && h.Date <= end);
return JsonConvert.SerializeObject(records);
}
And here is the url I tried to call the method, but it doesn't reach to the method.
http://localhost:11847/api/History/Get?apiKey=398cfa9b-8c5c-4cf4-b4f3-8904a827ff22&start=2014-01-01&end=2014-12-01
I also have changed the WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}",
defaults: new { id = RouteParameter.Optional }
);
from "api/{controller}/{id} to "api/{controller}/{action}

UPDATE 2022:
It's 2022 now. A lot has changed. There are plenty of clients out there. I will list my favourites.
Postman - Postman has improved since I answered this in 2014. Apart from being a client, it has other features like collaboration, scripting, importing endpoints from various sources like Open API etc. Pretty simple to use.
Thunder Client - A Visual Studio extension that has a similar feel as Postman but a pure API client.
For testing the api, you can use fiddler(http://www.telerik.com/fiddler) or a chrome app called postman.
You should also try the POSTMAN by http://www.getpostman.com/ which can be added to chrome as an app. It really good and lets you organize your apis.

I found out how to write the url in Fiddler:
In the Composer panel:
Parsed:
GET : http://localhost:11847/api/History/GetRecords?apiKey=398cfa9b-8c5c-4cf4-b4f3-8904a827ff22&start=2014-01-01&end=2014-12-01
Request Headers:
User-Agent: Fiddler
Content-Type: application/json
Host: localhost:11847
Content-Length: 0

Related

Passing Odata Query Options in the Request Body

In the Odata 4.01 URL conventions it says that for GET requests with extremely long filter expressions you can append /$query to the resource path of the URL, use the POST verb instead of GET, and pass the query options part of the URL in the request body. If I try that with my service I get back a 404.
Does the /$query endpoint need to be manually created in the back end or is this something odata is supposed to take care of transparently? I've been searching like crazy but I'm having trouble finding anything about how to implement this.
To support this you add app.UseODataQueryRequest() to your startup somewhere before app.UseRouting()
The framework then transforms ~/$query POST requests into GET requests which are handled by the HttpGet action methods on your controller (source).
Documentation is here (although currently not up to date)
For a complete sample have a look here
One way to avoid this is wrapping the request in a batch request
You can resolve long url with $batch query.
Good post from Hassan Habib https://devblogs.microsoft.com/odata/all-in-one-with-odata-batch//
All what you should do is:
Allow batching in Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseODataBatching(); <---- (1)
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.Select().Filter().Expand().OrderBy();
endpoints.MapODataRoute(
routeName: "api",
routePrefix: "api",
model: GetEdmModel(),
batchHandler: new DefaultODataBatchHandler()); <---- (2)
});
}
Request batch query with body, that contains long url request
POST http://localhost/api/$batch
Content-Type: multipart/mixed; boundary=batch_mybatch
body:
--batch_mybatch
Content-Type: application/http
Content-Transfer-Encoding: binary
GET http://localhost/api/students/735b6ae6-485e-4ad8-a993-36227ac82851 HTTP/1.1 <--long url requst
OData-Version: 4.0
OData-MaxVersion: 4.0
Accept: application/json;odata.metadata=minimal
Accept-Charset: UTF-8
User-Agent: Microsoft ADO.NET Data Services
--batch_mybatch

JSon to WebAPI becomes [[]],[[]],[[]],[[]]

something strange is happening with my WebAPI that I can't seem to figure out yet.
I'm using SoapUI to post this payload:
{
'Id': '00000000-0000-0000-1821-000000000000',
'Operation': 'post',
'Severity': 1,
'LoginName': 'nickj#noemail.email',
'EventText': 'testing post method'
}
My WebAPI is just this:
public HttpResponseMessage PostTrackingInformation(HttpRequestMessage req)
{
var content = req.Content;
string jsonContent = content.ReadAsStringAsync().Result;
}
However, when I look at the string content, I end up with content that looks like this:
[[[]],[[]],[[]],[[]],[[]]]
I am sending in application/json as the Content-Type
Has anybody seen this before? What am I missing?
Thanks,
Nick
This turns out to not be an issue with the API itself, but with Restsharp 106.69's version and Newtonsoft.
I ended up adding this package:
using RestSharp.Serializers.Newtonsoft.Json;
and then my Restsharp Request lines like this:
var request = new RestSharp.RestRequest {Method =
Method.POST, RequestFormat = DataFormat.Json, JsonSerializer = new
NewtonsoftJsonSerializer()};
It also sounds like the next major version of RestSharp (107) will support Newtonsoft Again.

Invalid character returned in IE but not in Firefox and Chrome

I'm using fetch to return a JSON payload to a React SPA. My web server backend is ASP.NET Core 2.0. I recently updated to ASP.NET Core 2.0 and for the life of me can't figure out why IE no longer works with the web application.
The fetch is pretty straight forward.
fetch(getApiPath() + url, {
credentials: 'include'
})
.then(function(response){
if (response.status === 401 && history) {
history.push("/login")
throw new Error('Redirecting to login');
} else if (response.status === 200) {
return response.json();
} else {
throw new Error(response.statusText);
}
})
.then(success)
.catch(function(e) {
console.log(e)
});
The server end is also pretty straight forward.
[Authorize]
[Route("/dashboard")]
public object Index()
{
Log.Debug("Index");
return new { dashboard = _dashboard, authenticated = HttpContext.User.Identity.IsAuthenticated };
}
The problem manifests itself in a "Invalid Character" error in IE. This works fine in Chrome and Firefox. When looking at the response body, the IE response, is in fact an invalid character while in Chrome, it is the JSON payload.
I'm a little unsure where to even start looking into why IE wouldn't receive or parse the HTTP response correctly. Any ideas?
EDIT:
Making a cross-origin request from a Webpack Dev Server running on port 10000 to a local ASP.NET Core app running on 10001. When packaged for deployment, both the React App and the ASP.NET Core App run on 10000.
Headers between the two requests.
IE Request
IE Response
Chrome
Updated the endpoint to return an IActionResult and explicitly returning JSON. Same result. I've also realized it doesn't work in Edge either.
[Authorize]
[Route("/dashboard")]
public IActionResult Index()
{
return Json(
new { dashboard = _dashboard, authenticated = HttpContext.User.Identity.IsAuthenticated }
);
}
Without additional info I suspect the issue is related to ASP.Net's content negotiation and the fact your method return type is object. Don't use object, this is not Java :))
Before anything else, make sure fetch is sending an Accept: application/json header in IE.
I would also recommend for you to change the return type to IActionResult (or JSONResult if you want to force JSON) for your controller methods.

Getting access_token from identityserver returns null

I have 3 projects, an MVC .net core website, an API service and an IdentityServer (IdentityServer4). Logging in to the website works like a charm. It's when I want to get data from the API the problems are starting. Getting the access_token from the httpcontext fails and returns null. The strange thing is that when I debug this, I seem to be getting an access_token back from the httpcontext. Only when I run the website from the live webserver it causes problems.
I configured my OpenIdConnect as follows:
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultAuthenticateScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "https://idserverurl";
options.RequireHttpsMetadata = true;
options.ClientId = "clientid";
options.ClientSecret = "xxxxxxxx";
options.ResponseType = "code id_token";
options.SaveTokens = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("offline_access");
};
});
To set the bearertoken for the API calls I use de following code:
var client = new HttpClient();
var accessToken = await HttpContext.GetTokenAsync("access_token");
client.SetBearerToken(accessToken);
When I run this code in debug I get the access_token from the HttpContext. When I run this from the live servers, I get null.
Does anybody have any idea what I'm doing wrong? Could it be a configuration mistake at server level?
I think I solved it myself.
It had to do with the line
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
By removing this line and altering the lines of code where I get my claims (they have a different key now), I am getting the access_token.
FYI I published the project to my own IIS. That way I could attach Visual Studio to the dotnet process and debug it.
Why it worked locally and not online I still don't know.
The above code looks OK - ultimately the tokens should come back from the Authorization Server after user login, then be persisted between requests in the authentication cookie.
Are you able to run Fiddler on your live web server and capture a trace of traffic, including that between your Web App and the Authorization Server? That's the ideal way to troubleshoot - and see if the expected tokens / cookies are present in the HTTPS requests.
In case you're not aware, in .Net Core 2.0 you can construct your web app's HttpClient with an HttpClientHandler that sets proxy details like this:
public class ProxyHttpHandler : HttpClientHandler
{
public ProxyHttpHandler()
{
this.Proxy = new WebProxy("http://127.0.0.1:8888");
}
}
In older versions of MS OpenIdConnect libraries I've seen problems related to load balancing, where not all servers could decrypt the authentication cookie. So if your live servers are load balanced the details in this older link may be relevant.

how to prevent internet explorer from caching ajax request in angular2, typescript?

Scenario is that user have some points lets say 10 pts. so after clicking on button an ajax get call sent to server that update the points of user as he/she consumed it. So, server should send 9 which is working on all browsers except Internet Explorer. After searching I found that IE not even making the request it is caching that request. How to solve this issue ?
Thanx in advance !
If you have control on the server code, you should set the appropriate headers that disallow caching.
You can set the headers
Cache-Control: no-cache
Expires: -1
A possible approach would be to implement an HTTP interceptor and append a timestamp if the request with the URL has already been executed.
#Injectable()
export class CustomHttp extends Http {
urls: {string:string} = {};
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
if (this.urls[url]) {
options = options || {};
options.search = options.search || new URLSearchParams();
options.search.set('timestamp', (new Date()).getTime());
}
return super.get(url, options).do(() => {
this.urls[url] = true;
});
}
}

Resources