Model Binder not working on first request after App Pool recycle - c#

I have a problem with the model binder. Each time after I recycle the App Pool, the first request to the server fails to perform model binding. Request.InputStream has the proper request parameters, but the Action parameters are null and Request.Params does not contain them either.
This appears to happen on the first POST request with JSON. The real first request is a GET to Index(), which returns the view. After that, the client makes an AJAX request that fails.
This is what my Action looks like:
public async Task<ActionResult> GetQueryCounters(string query) { ... }
This is the contents of Request.InputStream on the first request (it's the same on subsequent requests):
{"query":"SELECT count(*) FROM accounts"}
This is the raw request as seen in Fiddler:
POST https://[url]/GetQueryCounters HTTP/1.1
Host: [url]
Connection: keep-alive
Content-Length: 281
Origin: https://[url]
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36
Content-Type: application/json; charset=UTF-8
Accept: application/json, text/javascript, */*; q=0.01
x-ajaxRequest: true
X-Requested-With: XMLHttpRequest
__RequestVerificationToken: [snip]
Referer: https://[url]
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,he;q=0.6
Cookie: [snip]
{"query":"SELECT count(*) FROM accounts"}
What could be causing this?

Related

Angular 405 Method not allowed and "Provisional Headers are shown" error

This is driving me insane. I am trying to send a simple request to my api server and appending the header. It is first giving me this Provisional Headers are shown message then it will fail on the next request
Provisional headers are shown
Accept: application/json, text/plain, */*
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Expires: Sat, 01 Jan 2000 00:00:00 GMT
Pragma: no-cache
Referer: https://mywebsite.com/
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36
If I add the below data in my intercept method then I get the error.
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
request = request.clone({ headers: request.headers.set('Access-Control-Allow-Credentials', 'true') });
request = request.clone({ headers: request.headers.set('Cache-Control', 'no-cache') });
request = request.clone({ headers: request.headers.set('Pragma', 'no-cache') });
request = request.clone({ headers: request.headers.set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT') });
return next.handle(request);
}
If I remove it and do not add the headers then I don't get an error but eventually I will need to send other data in the header like an authtoken and user id.
Why am I getting this 405 error when appending to the headers?
Also why is it telling me method not allowed when I clearly am allowing Options and Post methods
I had this same problem about a month ago.
You need to create a basic http ok response for the Options verb. Put this in your base api controller. The options request is sent first and it needs an ok response callback before it can proceed with passing Options to the API
public HttpResponseMessage Options()
{
return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}
Try add
API Key in header (e.g.: x-my-api-key)
API Value in header (e.g.: 7e807890-c777-466a-897)
Hope this could help...

Requesting to github-api using .net HttpClient says Forbidden

I am trying to getting data from this github api link https://api.github.com/users/arif2009 . It works fine using posman get request.
But if i try to get data using .net HttpClient then it says Forbidden.
C# code:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("users/arif2009");
if (response.IsSuccessStatusCode)
{
var data = response.Content.ReadAsAsync<GithubUser>();
}
}
Response:
Can anybody tell me where i made the mistake?
I took a look at your requests using Telerik's Fiddler and found the following.
Request with your code:
GET https://api.github.com/users/arif2009 HTTP/1.1
Accept: application/json
Host: api.github.com
Request from Postman:
GET https://api.github.com/users/arif2009 HTTP/1.1
Host: api.github.com
Connection: keep-alive
Accept: application/json
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Postman-Token: d560ee28-b1e8-ece5-2612-87371ddcb295
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,ja-JP;q=0.8,ja;q=0.7,en-US;q=0.6
The obvious missing header seemed to be "User-Agent", so I added this:
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("product", "1")); // set your own values here
Which produced the following request:
GET https://api.github.com/users/arif2009 HTTP/1.1
Accept: application/json
User-Agent: product/1
Host: api.github.com
And returned the following response:
HTTP/1.1 200 OK
Date: Wed, 17 Jul 2019 15:19:35 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 1249
Server: GitHub.com
Status: 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 52
X-RateLimit-Reset: 1563380375
Cache-Control: public, max-age=60, s-maxage=60
Vary: Accept
ETag: "1df3e0be6e824ca684f27963806533da"
Last-Modified: Tue, 16 Jul 2019 05:58:59 GMT
X-GitHub-Media-Type: github.v3
Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type
Access-Control-Allow-Origin: *
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
X-Frame-Options: deny
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
Content-Security-Policy: default-src 'none'
Vary: Accept-Encoding
X-GitHub-Request-Id: D5E0:8D63:8BE92C:A799AE:5D2F3C86
{"login":"arif2009","id":6396346,"node_id":"MDQ6VXNlcjYzOTYzNDY=","avatar_url":"https://avatars0.githubusercontent.com/u/6396346?v=4","gravatar_id":"","url":"https://api.github.com/users/arif2009","html_url":"https://github.com/arif2009","followers_url":"https://api.github.com/users/arif2009/followers","following_url":"https://api.github.com/users/arif2009/following{/other_user}","gists_url":"https://api.github.com/users/arif2009/gists{/gist_id}","starred_url":"https://api.github.com/users/arif2009/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arif2009/subscriptions","organizations_url":"https://api.github.com/users/arif2009/orgs","repos_url":"https://api.github.com/users/arif2009/repos","events_url":"https://api.github.com/users/arif2009/events{/privacy}","received_events_url":"https://api.github.com/users/arif2009/received_events","type":"User","site_admin":false,"name":"Arif","company":"#BrainStation-23 ","blog":"https://arif2009.github.io/","location":"Bangladesh","email":null,"hireable":true,"bio":"Software Engineer | Full Stack | Web Developer | Technical Writer","public_repos":15,"public_gists":2,"followers":9,"following":7,"created_at":"2014-01-14T05:03:47Z","updated_at":"2019-07-16T05:58:59Z"}
this API reference from github says that 'User-Agent' is a required header:
All API requests MUST include a valid User-Agent header. Requests with no User-Agent header will be rejected.
Postman automatically adds its own User-Agent to the call when this is not provided by the user. (This is nicely demonstrated by #John's answer).
simply adding this header will resolve your issue:
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("yourAppName", "yourVersionNumber"));
You may try to put the complete URI into the GetAsync instead using the BaseAddress, as you do not give the GetAsync an URI, but only a string.
When sending a HttpRequestMessage with a relative Uri, the message Uri will be added to the BaseAddress property to create an absolute Uri.
https://learn.microsoft.com/de-de/dotnet/api/system.net.http.httpclient.baseaddress?view=netframework-4.8

Why do I get an empty response?

I am sending:
GET / HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv28.0) Gecko/20100101 Firefox/28.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
My Code:
htmlClient.Connect(Dns.GetHostAddresses(url.Host)[0], 80); // Connect to server on port 80
htmlClient.Send(ASCIIEncoding.Default.GetBytes(htmlreq));
byte[] htmlReqBuff = new byte[10240];
htmlClient.Receive(htmlReqBuff);
htmlClient.Disconnect(false);
htmlClient.Shutdown(SocketShutdown.Both);
htmlClient.Dispose();
Log.info(ASCIIEncoding.Default.GetString(htmlReqBuff));
From some Webservers I get an request timeout.
Your request must end with a empty line <CR><LF> to indicate the end of the HTTP request.

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.

Which HTTP header must be sent when call webrequest or webclient?

I am creating a web robot. Usually the http tools returns quite a few information and some of these are readonly (e.g. Connect: keep-alive). How to know which ones are required?
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Charset: ISO-8859-9,utf-8;q=0.7,*;q=0.3
Accept-Encoding: gzip,deflate,sdch
Accept-Language: tr-TR,tr;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control: max-age=0
Content-Length: 269
Content-Type: application/x-www-form-urlencoded
Host: closure-compiler.appspot.com
Origin: null
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.794.0 Safari/535.1
Usually the code looks like the following. Someone pointed out that the following code missed to set Content-Type?
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://closure-compiler.appspot.com/compile");
req.Connection = "keep-alive";
req.Headers.Add("Cache-Control", "max-age=0");
req.Headers.Add("Origin","null");
req.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.794.0 Safari/535.1";
req.ContentType = "application/x-www-form-urlencoded";
req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
req.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");
req.Headers.Add("Accept-Language", "tr-TR,tr;q=0.8,en-US;q=0.6,en;q=0.4");
req.Headers.Add("Accept-Charset", " ISO-8859-9,utf-8;q=0.7,*;q=0.3");
req.Method = "POST";
Stream reqStr = req.GetRequestStream();
No headers are required for general requests. Particular resources may require different headers. The right way is to ask owner of the resource what headers are needed. But if you want to cheat in some sort of game/forum you will have to figure out headers and other values yourself.
According to w3.org the simplest request should look somewhat similar to this:
GET <uri> CrLf
Thst's all.

Categories