Blazor Webassembly, custom http response headers - blazor-client-side

I'm creating Blazor Webassembly app, which call my Dotnet web API. I'm using the injected http client, and the api call itself run without problems, Postmann & WireShark confirms that my custom response headers from the API is returned correctly. But in the Blazor Webassembly app, there is only one header "content-type". I know that the Blazor Http client is a wrapper around some Javascript, but are there anyone out there that can help with some knowledge or examples on how to get custom response headers thru to the Blazor app.
I'm using Visual Studio 2019 Community and also Visual Studio Code, and normally I develop on a Mac, but due to problems with debugging Blazor apps on Mac I changed to Windows 10.

It was actually very simple. To allow my custom response headers to be available in a Blazor Webassembly app, On the server API, just add below header to the response:
HttpContext.Response.Headers.Add(" Access-Control-Expose-Headers","YourCustomHeader,YourOtherCustomHeader");

As #Jagdriver mentioned, adding:
HttpContext.Response.Headers.Add("Access-Control-Expose-Headers", "my-header");
will add an extra header to the response in order to indicate which headers may be processed, additionally to the safe headers.
About .NET, the headers can be retrieved into a dedicated property of the response:
HttpClient http = new();
HttpResponseMessage response = await http.GetAsync("https://...");
string MyHeader = "my-header";
KeyValuePair<string, HeaderStringValues> nvHeaders =
response.Headers.NonValidated
.Where(v => v.Key == MyHeader)
.FirstOrDefault();
// KeyValuePair is a struct, default value is a KeyValuePair where the Key is null.
if (!string.IsNullOrEmpty(nv.Key))
{
string MyHeaderValue = nv.Value.FirstOrDefault();
}

Related

How to add SignalR request Headers on .net client side

I have server side Hub with the following code:
private string GetUserPhoneFromContext()
{
var httpCtx = Context.GetHttpContext();
return httpCtx.Request.Headers["userPhone"].ToString();
}
Mention above code I can't change it works on prod with flutter clients.
I am developing blazor wasm client side and on client side I want to add headers as follow:
hubConnection = new HubConnectionBuilder()
.WithUrl($"{Uri}?userPhone={Phone}", options =>
{
options.Headers.Add("userPhone", Phone);
})
.WithAutomaticReconnect()
.Build();
But nor via options.Header.Add() neither via adding query string parameter I can't read header on the server side via GetUserPhoneFromContext method, I always get empty string instead of added on client userPhone header. Not clearly understand why it works with flutter clients but does not work with .net blazor wasm
I find out the root. The Blazor WASM SignalR implemetation is a wrapper around JS implementation that does not support Headers. If you need additional data use QueryString
see https://github.com/dotnet/aspnetcore/issues/18694 for more

HttpClient.GetAsync works with LocalHost API, but not Live API

I have a .Net 4.5.2 WebApp that is calling my API. When I point my web app to the LocalHost version of my API, it gets the data, and comes back just fine. I published that API, and confirm that the API is working correctly with PostMan.
Then I run the exact same WebApp code, changing only the URI from localhost to live api, and I get a multiple exception error consisting of the following:
An existing connection was forcibly closed by the remote host
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
The underlying connection was closed: An unexpected error occurred on a send.
An error occurred while sending the request.
Here's my calling code
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("user", serializedUser);
response = null;
try
{
//Uri uri = new Uri("https://jsonplaceholder.typicode.com/posts/1");//https works
Uri uri = new Uri("https://api.acme.com/values/test");
//Uri uri = new Uri("http://localhost/5000/values/test"); //http localhost works
response = client.GetAsync(uri).Result;
}
catch (Exception e)
{
string er = e.Message;
}
}
EDIT 1: I created a .NET Core app from scratch, and my original code works perfectly calling my live API. My original code also work in .NET 4.5.2 calling a different "https" API.
EDIT 2:
So this is where I'm at now, I have created two generic apps from VS 2015, one is a .NET Core Web App, the other a .NET Framework Web App. I have used the above code exactly the same in both apps to call the API. In both apps, I can call a generic "https" api I found online (jsonplaceholder). I can also call the localhost version of my app at "http" from both. In the .NET Core version of the app, I can call my "https" live API and get the results I'm looking for. In the .NET Framework app I still get the same errors.
I can't figure out what the difference is between my Core and Framework requests that is getting one shut down when the other isn't.
It seems you are hosting the application on secured http environment (https). Are you using SSL certificate on the server where you are hosting your Web API? If not, It might be throwing the certificate related exceptions.
Just add the following line before the call to GetAsync and This will ignore the SSL errors.
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
This is only recommended in an intranet environment or other closed network where server identities can't be forged.
C# Ignore certificate errors?
Adding the following line before my API call fixed the issue, but I'd love to hear an explanation of what this line does, and any security risks this might impose using it in my web app.
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Props to this answer!

Windows 8.1 application does not do the NTLM Negotiation required by Windows Authentication

I have a Windows 8.1 Store application that I side-load on a Windows 10 Enterprise DELL tablet. The app uses data from a repository via an ASP.NET Web API installed on a remote server. The Web API is configured to use Windows Authentication. If I use Fiddler to make Web API calls I can see the several steps in the NTLM negotiation, the 401.2 HTTP Error messages returned twice before the HTTP 200 Ok.
However, my application gets the 401.1 and then it does not do anything else. In my application's package manifest, I have checked Enterprise Authentication check box in the list of required capabilities. Also, when I tested it with the Visual Studio Simulator, on my development machine, the negotiation was done and the Web API responded properly to my calls.
In order to have the NTLM Negotiation done automatically in the background, I though all that needs to be done is to have an HttpClientHandler object constructed like this:
var webApiAuthClientHandler = new HttpClientHandler()
{
Credentials = CredentialCache.DefaultNetworkCredentials,
ClientCertificateOptions = ClientCertificateOption.Automatic
};
Then, this HttpClientHandler object would be passed in the constructor of the HttpClient object used to make the Web API calls:
var webApiHttpClient = new HttpClient(webApiAuthClientHandler)
{
BaseAddress = new Uri(_myWebApiUri, UriKind.Absolute),
Timeout = new TimeSpan(0, 0, 150)
};
What am I missing? How do I get my app to automatically negotiate the authentication in the background and have my GetAsync call return the needed HTTP Code 200?
Any suggestion would be highly appreciated.
TIA,
Eddie
I see your issue has been resolved in MSDN forum: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/58620579-240d-49da-8538-cee5aff91a68/w81-sideloaded-windows-81-application-generates-an-exception-when-calling-methods-of-an-restful?forum=wpdevelop
So I post it here to help more visitors find the solution easily.
Thank you.

Do I need to do something special in the ASP.NET MVC app to read a Json response from a Web API 2 application?

Is there something special I need to define in an ASP.NET MVC application to read an incoming response from a ASP.NET Web API?
From my MVC app, I make a request to an ASP.NET Web API using System.Net.HttpClient. The API receives the request and processes it fine and returns a valid response. However, the MVC application, it appears, never gets the response. I have a break point on the line that makes the request. The flow of control never comes back after executing that line. The MVC app just keeps waiting and times-out after a very long time.
However, I can confirm that the API returns a valid Json response. I have tried composing this request in Chrome Postman and see that the API returns a valid response.
Here's the code from my MVC app that makes the request to the Web API:
public async Task<R> PostAsJsonAsync<T, R>(string uri, T value)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseUri);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.PostAsJsonAsync(uri, value);
if (response.IsSuccessStatusCode) return await response.Content.ReadAsAsync<R>();
else return default(R);
}
}
In the past, i.e. before Web API 2, I've had MVC apps talk to the Web API without any problem. I don't know if I am missing something that has been introduced in Web API 2.
I have a feeling you are getting a deadlock. Are you using .Result anywhere? You should be using async all the way. I mean your MVC action method should also be async method and they should await and not use .Result. Read this log post by Stephen Cleary for more info. http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

Override OPTIONS response in NancyFX / Visual Studio Web Server

I've build a RESTful web service using NancyFX which I'm now trying to POST to from a separate domain. Of course when I do that, I see a failed OPTIONS message in the console because this is a Cross Site POST and I need to ensure that Nancy responds correctly to the OPTIONS message being sent by the browser. However, when I define a route in my Nancy module:
this.Options["/options/"] = _ => this.OptionsRequest();
private dynamic OptionsRequest()
{
return this.Response.AsJson(Request)
.WithHeader("Access-Control-Allow-Origin", "*")
.WithHeader("Access-Control-Allow-Methods", "POST")
.WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type");
}
The code never gets hit. I can set a breakpoint on the OptionsRequest() method in debugger and see that the code is never getting hit. However I can issue an OPTIONS request in postman, and the server returns a response (interestingly, it seems to return a response from all URIs, not just the /options/ route I've defined).
Is there a default Nancy OPTIONS behaviour I have to override in order to specify routes for OPTIONS, or is this something to do with the service being hosted in the Visual Studio Development Web Server (Casini)? I've tried everything I can think of and I'm still stumped as to why I can't define behaviour for this particular verb.
Turns out this was a bug in Nancy v0.17.1 (see https://github.com/NancyFx/Nancy/pull/1093). Upgrading to 0.18.0 fixed the issue and allowed my OPTIONS route to work correctly.

Resources