Web api behaves "stateful" in some successive calls from different client issue - c#

I have a web api consumed by mobile apps. I can reproduce case with postman also with appropriate params.
Here are my postman call captured by fiddler:
GET http://localhost/WebApi/api/User/GetAnnouncement?id=22 HTTP/1.1
Content-Type: application/json
ApiKey: someKey
AuthenticationToken: someGuid1
UserId: 6524
DeviceId: someGuid2
LocalDate: 538294155.662561
OsTypeId: 1
LoginToken: someGuid3
CompanyId: 2
cache-control: no-cache
Postman-Token: b863afdd-b04c-4a4d-b473-69d5ecef622e
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Host: localhost
cookie: ASP.NET_SessionId=nk4g3zzfyi0n3xomfw5dxxxx
accept-encoding: gzip, deflate
Connection: keep-alive
and my issue occurs in authorize action filter:
public class BasicAuthorizeAttribute : FilterAttribute
{
}
public class BasicAuthorizeFilter : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
//!!!HERE when I debug, in watch I can see already authHeader has value "in some calls"
System.Threading.Thread.SetData( System.Threading.Thread.GetNamedDataSlot("authHeader"), "someValueComingFromRequestHeader" );
}
}
At the very beginning of the OnAuthorization (see !!!HERE line in the code), I can see in watch this expression:
System.Threading.Thread.GetData(System.Threading.Thread.GetNamedDataSlot("authHeader"))
has the value even though I expect it is always null. It has even the value from previous client.
Actually issue come to as a bug "session" mingled (I mean mixed).
This pieces code is on the my company's framework so something is weirdly wrong.
I can give as much as I can so far. Please ask any info necessary.
What could be the cause?
I am daring to ask this because it is possible the issue obvious may be.
Note: I have the same case while none debugging with two phones connected to my pc via proxy settings.

Related

ASP.NET Web API 2.0 Parameters Null

I know it's been asked a lot of time and I have tried everything but still facing the problem. Here is my code:
// POST api/<controller>
public string Post([FromBody]string value)
{
return value;
}
There is nothing fancy just returning the value.
I am using Chrome's PostMan Plugin
I have tried like 100 times but still getting the same null value as the response. I have tried it with Content-Type application/json and everything mentioned but still getting null.
Not really sure what the question is however what you are looking for is to setup your POST with a single value.
Such as below:
POST /api/values HTTP/1.1
Host: localhost:50121
Content-Type: application/json
Accept: application/json, text/javascript
Cache-Control: no-cache
'abc'
Now this is a JSON post so the body doesn't have a parameter name, this is by design as you are posting a single value.
If you need multiple values or a more complex object you should use a class object instead of a single value.

100K sized POST requests don't get to webAPI?

I'm using Fiddler (or post manager) to invoke requests to my WebApi. ( it's hosted as an ASP.net application in IIS)
This is the service :
[HttpPost]
[ActionName("uploadRessources")]
[AllowAnonymous]
public HttpResponseMessage uploadRessources(ResourcesJson json)
{
...
return Request.CreateResponse(HttpStatusCode.OK, result);
}
For short length body( 3 rows of data) length post data requests like :
POST http://something.com/api/services/uploadRessources HTTP/1.1
Cache-Control: no-cache
Connection: keep-alive
Pragma: no-cache
Accept: application/json
Accept-Encoding: gzip
Accept-Language: he-IL
User-Agent: Mozilla/5.0
Content-Length: 451
Content-Type: application/json
Host: es.com
{ "l":
[{"MasterEntity":2,"screen":"ConfirmHealthDetailsPage","Lbl":"ApproveTheFollowingDetails","enus":"Approve the Following Details:","device":"mobile","description":"NULL"},
{"MasterEntity":2,"screen":"ConfirmHealthDetailsPage","Lbl":"PersonalDetails","enus":"Personal Details","device":"mobile","description":"NULL"},
{"MasterEntity":2,"screen":"FingerPrintResources","Lbl":"CANCEL","enus":"CANCEL","device":"mobile","description":"NULL"}]
}
I DO get a successful response :
HTTP/1.1 200 OK
But for a long body length request ( 101K ) -
It is stuck (it even doesn't hit the breakpoint in my code , while in short request - it does )and I never see a response :
BTW - If later I do run again the short body length request( while still waiting for the previous large requests) - I do get 200 ( for the short length request).
In web.config I did set :
<httpRuntime enableVersionHeader="false" executionTimeout="100000000" maxRequestLength="999999999" />
In IIS : No requests filters
In Event Viewer - I don't see any exceptions or warnings
IIS version : 6.1 ( windows 7) - but it also happens at our server.
Question
Why doesn't my 101k length request - get to my webapi ?
Edit
I've found that it happens for >65k requests. Still don't know what is the problem
It's seems to be an issue with your serializer, tries to put a breakpoint there and see if hits it. If you are not using a custom serializer, creates one temporally just to see what's happen with your request.
It was stuck on request.Content.ReadAsStringAsync().Result ( and never released). Strange but setting it to async , solved the problem. I still don't know why. In General this is the solution - the left pane was the problematic one while the right pane is the working one. ( I must say that the left pane used to work , but after upgrading to 4.6.2 - it started doing problems) - Again - I don't know why

Null parameter in OData Custom Action

I want a custom action added in my OData controller for adding an entity. I can do that in standard Post method supplied in OData controller but I have some custom code that get's overwritten when I refresh the controller from database if I add an association.
Here is the custom method I've added
[HttpPost]
public IHttpActionResult CreateValidCombination(ValidCombination validCombination)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok();
}
The request header is same as the standard post method
POST http://localhost:20152/Admin/odata/ValidCombinations/fn.CreateValidCombination HTTP/1.1
Accept: */*
Content-Type: application/json
Referer: http://localhost:20152/Admin/index.html
Accept-Language: en-CA,en;q=0.5
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 284
DNT: 1
Host: localhost:20152
Pragma: no-cache
The Action is configured in WebApiConfig.cs as
builder.EntityType<ValidCombination>().Collection
.Action("CreateValidCombination")
.Returns<IHttpActionResult>();
The problem is while the standard OData Contoller Post method receives the parameter of type "ValidCombination" proper, customer method receives it as null.
I've checked request headers and body in fiddler and its same in both the cases. I've even tried putting [FromBody] in front of the parameter but to no avail. I am trying to get value into the parameter for my custom method.
Has anyone faced this situation before. Is there a way I can debug why the parameter is not properly being deserialized even though request and body are same for both the methods?
According to http://odata.github.io/WebApi/#04-07-action-parameter-support, in your customized action method, parameter type should be ODataActionParameters instead of ValidCombination, OData WebApi's code is in github, is very easy to debug, you can find lots of function tests too.

Does it matter that a servicestack.net OPTIONS request returns a 404?

I'm using the method described at https://github.com/ServiceStack/ServiceStack/wiki/New-Api to enable CORS. This seems to work, i.e. I get the correct Access-Control headers back in the response, but the status code is a 404. Does this matter?
For completeness I'd prefer to return a non-error code. Reading http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html it seems as though I ought to be returning a 200. What's the best way to do this?
The service method definition is:-
[EnableCors]
public void Options(ApiKeyRequest apiKeyRequest)
{
}
The HTTP request is:-
OPTIONS http://myreallycoolwebapi/apikeyrequests HTTP/1.1
Host: myreallycoolwebapi
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:8000
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11
Access-Control-Request-Headers: origin, content-type, accept
Accept: */*
Referer: http://localhost:8000/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
and the response is:-
HTTP/1.1 404 Not Found
Server: nginx
Date: Sat, 17 Nov 2012 18:06:01 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 3
Connection: keep-alive
Cache-Control: private
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
404
UPDATE 1
This is my resource type.
[Route("/apikeyrequests", "POST")]
public class ApiKeyRequest : IReturn<ApiKeyRequest>
{
public string EmailAddress { get; set; }
}
The POST requests work just fine.
I still haven't seen anything matching the expected route /apikeyrequests.
Do you have a custom route definition, e.g:
[Route("/apikeyrequests")]
public class ApiKeyRequest {}
Added for the request?
The CORS spec itself explicitly indicates that a non-200 preflight response is an error. See the "If the response has an HTTP status code that is not 200" section here:
http://www.w3.org/TR/cors/#cross-origin-request-with-preflight-0
I don't know what the motivation is for this requirement. Perhaps its because a 404 could introduce confusion as to whether the endpoint actually exists.

HttpActionContext.Request.Headers.Authorization is null

I am using asp.net mvc 4 rest and write my own basec authentification logic.
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Authorization == null)
{
actionContext.Response = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
}
else
{
//do staff here
}
}
It works on local iis. But it does not work on producation station. I always get null. I set basic authentification enabled on IIS. I am testing with Fiddler and my request looks like that:
User-Agent: darwin/1.0 CFNetwork/548.1.4 Darwin/11.0.0
Authorization: Basic cmFkaWt2b3N0b2tAZ21haWwuY65tJjE6QkFBREVEcHlQYmtjQkFOcXh4UmFrdG1JMUJ2bjBPYXVQVk9NcnFZMEg4V3BhakljSlk2WkJMTWtra1FIWHFrcEZmdEkyNmFEZEppYWlKVVZJOTZpUGJuMzRMc1luemJHM2FPV3paQk5DTG1Xak9FZGU3YTdGWVhVem1QeTlEWkM4cW02YWZoWkJGWkIzbGFXMTNaQjlKdQ==
Content-Length: 10128
Accept: application/json
Content-Type: application/json
Connection: keep-alive
Host: 192.168.7.4
Does anybody know why it happens?
First of all, implement OnAuthorization() instead of OnActionExecuting(). OnAuthorization() is executed prior to OnActionExecuting(). It's important to check for authorization even before the user reaches OnActionExecuting() codes.
But your answer: the most possible situation is that the <authentication> is set to "None" in production web.config file. Change it as follows and you'll be all set:
<authentication mode="Forms"/>

Categories