Click here to Skip to main content
15,505,442 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hey guys, long time no see but i got a problem i can't solve, so i thought this might be the place to be!

Short introduction to what i am trying to achieve, because i thought that's how you do it properly.

I am fairly new to the Web stuff, but as i heard that the .NET Framework is probably going to die some day i wanted to start to shift my WPF stuff to web, hence start with the back end as REST service.

What i did is, i managed to get my REST API working on an IIS and everything looks fine and does what it should, proper authentication aside, since that's only a PoC.
I then began to write a Blazor server app that should work as admin dashboard for the "Server of my Application", hence the REST API that provides processor usage, memory usage, current user pools (Data Pools i create upon login of a user, some sort of small cache let's say). Basically that is my PoC for a structure later on to separate concerns and load on different servers. But for the start, and to estimate load and usage, i thought it could all run on one IIS

On my machine the Blazor app works like it should, it loggs me in as admin and displays the data and so on, but as soon as i deploy it on the same IIS like the REST API, they listen on different ports of course, it doesn't work and upon login i receive a 400 Bad request error.

Additional note: The Blazor app does Authentication via the built in authorization stuff and it also is using https with a certificate, the REST API is available on Http and Https.

Both work as expected until it comes to the point where the blazor app needs to talk to the REST API.

What I have tried:

I tried changing the http clients base adress from the real server name and port to localHost, added the certificate to the REST API because i thought i might be an issue if one endpoint is using https and the other isn't. I google fuu'd my ass off yesterday but either i am to lousy at searching or what i want to do is totally wrong.

Sorry for the long text, some code here:
-That is the route after the user clicks on log in.
-Note that the error message is just for me to see what's wrong
C#
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
        {
            returnUrl ??= Url.Content("~/");

            ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();

            if (ModelState.IsValid)
            {
                if(string.IsNullOrWhiteSpace(Input.UserLogin))
                    return Page();

                var imsServer = new HttpClient();
                imsServer.BaseAddress = new Uri("https://srvims:5556/");

                var userLoginData = new UserLoginData
                {
                    UserLogin = Input.UserLogin,
                    ApplicationOfOrigin = "ServerMonitor"
                };

                var content = JsonSerializer.Serialize(userLoginData);
                var response = await imsServer.PostAsync($"employeeService/logIn/",
                    new StringContent(content, Encoding.UTF8, "application/json"));

                Employee admin = null;

                if (response.IsSuccessStatusCode)
                {
                    var responseBody = response.Content.ReadAsStringAsync().Result;
                    admin = JsonSerializer.Deserialize<Employee>(responseBody, new JsonSerializerOptions
                    {
                        PropertyNameCaseInsensitive = true
                    });
                }

                if (admin == null)
                {
                    ErrorMessage = $"Login failed:{Environment.NewLine} ----- " +
                                   $"{response} ----- {imsServer}";
                    return Page();
                }

                await _signInManager.SignInAsync(admin, isPersistent: false);
                return LocalRedirect(returnUrl);
            }

            // If we got this far, something failed, redisplay form
            return Page();
        }


As said, the thing i really don't get, is that if the blazor app runs on my machine, all works like it should. If it runs on the IIS it does "crash" on the communication with the REST API.

-edit-

Allright, after Richard's hint regarding CORS i went down the interwebs and tried to do everything according to what i read there. But it still does not work, although i tried various different things here.
The updated API code (since as far as i understood i need to enable CORS on the API instead of the blazor app)

C#
//var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddCors(options =>
{
    options.AddDefaultPolicy(policy =>
        {
            policy.AllowAnyOrigin()
                .AllowAnyHeader()
                .AllowAnyMethod();
        });
});
//builder.Services.AddCors(options =>
//{
//    options.AddPolicy(name: MyAllowSpecificOrigins,
//        policy =>
//        {
//            policy.WithOrigins("https://srvims:5001")
//                .AllowAnyHeader()
//                .AllowAnyMethod();
//        });
//});

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddSingleton<IDatabaseManager, DatabaseManager>();
builder.Services.AddSingleton<IDataPoolManager, DataPoolManager>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

//app.UseHttpsRedirection();
app.UseRouting();

//app.UseCors(MyAllowSpecificOrigins);
app.UseCors();

app.UseAuthorization();

app.MapControllers();

app.Run();


And since i wanted to do it properly properly i also did this

C#
[EnableCors]
[HttpPost("logIn/")]
public async Task<ActionResult<EmployeeData>> LogInUserAsync(LoginData InUserLoginData)


I also did check the IIS again and added the web sockets thing because that also seemed to be an issue for the blazor app. I have really no clue where i walked the wrong way. All videos and guides said do this (stuff above) in your API and it'll work. :(

-edit

-edit NO 2+3-
Okay, i have no clue why but! if i use my 3rd test port that is bound to *:5557
it seems to work. So now another question would be why is that so?
My bindings within IIS
http://srvims:5555 (IP address of server)
https://srvims:5556 (IP address of server)
http://srvims:5557 (*)

Is there any reason why it only works with IP address * instead of the actual ip address or should i have gone for the IP instead of the server name?

Screw that, my wife told me that you don't bind to the IP address if there is no specific case for multiple certificates or the like. So i guess it works as it should.

-edit NO 2+3-

I'd appreciate any hints on what i do wrong. If more info is needed i'm happy to provide.

Thanks in advance :)
Posted
Updated 16-Aug-22 22:21pm
v4
Comments
Richard Deeming 16-Aug-22 3:45am    
"they listen on different ports of course"

That suggests a CORS problem:
Cross-Origin Resource Sharing (CORS) - HTTP | MDN[^]

Different ports means different origins. You'll need to update the API to send back an appropriate CORS policy to allow the Blazor app to make requests.
HobbyProggy 16-Aug-22 3:50am    
That's a good hint, i am currently also verifying the "Exception" i receive if i switch to https, which tells me that the ssl connection could not be made.
I'll dig through that link of yours!
HobbyProggy 17-Aug-22 1:37am    
Thanks Richard, that was the absolute right direction, it works now. :)

1 solution

As discussed in the comments, applications on different ports suggests a CORS problem:
Cross-Origin Resource Sharing (CORS) - HTTP | MDN[^]

Different ports means different origins. You'll need to update the API to send back an appropriate CORS policy to allow the Blazor app to make requests.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900