How to navigate from identity page to page in different folder - c#

I have an ASP.NET Web Application (using Razor pages not controllers) and I am trying to amend the register (identity) page so that once the user has registered (by an admin whos logged in already) it navigates to a Manage roles page and passes the UserId of the user just created.
This is my folder structure:
Currently I'm on the register page which is within the following path:
Areas/Identity/Pages/Account/Register.cshtml
and I am trying to navigate to a page thats simply within the Pages folder: Pages/ManageRoles.cshtml
Here is my code:
return RedirectToPage("./ManageRoles", new { id = user.Id });
but it doesn't work and gives me an error saying No page named './ManageRoles' matches the supplied values. I have also tried the code without the ./ and it still gave me the same error. I have also tried it without the userId part and it still didnt work.
Could someone help me?

Changed it to this and it worked:
return RedirectToPage("/ManageRoles", new { UserId = user.Id });

Related

Creating a dynamic route

I am trying to create dynamic routes using ASP.Net Core and Razor Pages. Basically, I have two razor pages. One is called Pages/Home.cshtml and another is called Pages/Calendar.cshtml. Each user that logs in has their own username. So let's say I have two users in my database, Sam and Jessica and let's say Sam is logged in and goes to http://www.example.com/Sam, then it should render Pages/Home.cshtml. If Sam is logged in and goes to http://www.example.com/Sam/Calendar, then it should render Pages/Calendar.cshtml. If Jessica is logged in and she goes to http://www.example/com/Jessica, then it should render Pages/Home.cshtml.
So basically, ASP.Net Core should look at the URL and compare the username with what's in the database. If the signed in user's username matches the URL, then it should render their home page. If their username does not match the URL then it should continue down the routing pipeline. I don't need help with the database stuff or anything like that. I only need assistance on how to set up the routing.
If all this sounds confusing, then just think of Facebook. It should work exactly like Facebook. If you go to http://www.facebook.com/<your.user.name>, then it brings up your time line. If you go to http://www.facebook.com/<your.user.name>/friends, then it brings up your friends list.
I am basically trying to duplicate that same behavior that Facebook has in ASP.Net Core and Razor Pages. Can someone please provide a simple example or point me to an example? I feel like the way to do this is to use some custom middleware or a custom route attribute, but I am not sure.
You can do something like this. In the Program.cs/startup.cs modify the AddRazorPages like this.
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorPages(options =>
{
options.Conventions.AddPageRoute("/Index", "{user}");
options.Conventions.AddPageRoute("/Calendar", "{user}/calendar");
});
var app = builder.Build();
Now when you access a URL like https://localhost:7131/sam/calendar you will get the calendar page. You can access the user variable like this - #RouteData.Values["user"]
And on the calendar page, you can do something like this.
public class CalendarModel : PageModel
{
public void OnGet()
{
var user = RouteData.Values["user"];
//Query the calendar information from Database.
//If empty redirect the user to the home page or something.
}
}
You can find more details about this here - Razor Pages route and app conventions in ASP.NET Core

Html.AntiForgeryToken() throws error "Server cannot append header after HTTP headers have been sent."

I'm working on a self-made project and i am getting the error mentioned above. I created 2 roles that i give to the users during registration. These 2 roles gives privileges to the users to interact with certain parts of my webpage.
"User" role would give access to ~/Jobs/Jobs and "HR" role would give access to ~/Profile/Profiles. In my page layout view that responsibles for the navigation bar it works perfectly fine. I only see the specific button on my navbar when i have the required role to see it.
Before i created these roles i just used a !User.Identity.IsAuthenticated() condition that redirected the user to the login page if the user is not logged in. This condition is was the starting condition of my role-specific .cshtml files.
#{
if (!User.Identity.IsAuthenticated())
{
Response.Redirect("~/Account/Login");
}
}
...
It was working fine.
Now i have my roles and i changed it to !User.Identity.IsInRole(string parameter) condition that would redirect the user to the home page but i get the error mentioned above. Now this condition is the starting condition of my role-specific .cshtml files.
#{
if (!User.IsInRole("User")) // or "HR" on the other page
{
Response.Redirect("~/Home/Index/");
}
}
...
My error is popping up in my _LoginPartial.cshtml file.
#using Microsoft.AspNet.Identity
#if (Request.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id =
"logoutForm", #class = "navbar-right" }))
{
#Html.AntiForgeryToken()
...
I am getting the error when i'm trying to reach a role-specific page that i'm not allowed to reach. For example trying to reach a "HR" role-required page (~/Profile/Profiles) as a "User" throws me the error and vice versa. I'd like to be redirected instead of this error.
So i have 2 questions. Why do i get the error with the User.IsInRole(string parameter) condition and what does #Html.AntiForgeryToken() do? I'd like to understand it. :)
I have found a solution. Instead of trying to handle this in the view i handled it in my controller. Although i still don't understand why it caused problem(s) in my view.

Response.Redirect problam

I have a basic project with a menu bar that the server executes on each page. I want to prevent the access to the pages for unregistered users, so I added this code
if (Session["username"] == null)
Response.Redirect("HomePageWebSite.aspx");
When I load the HomePage by its self it works normaly, but when I use this code, the browser says that it can't find this page(unable to access this page). I checked the url of the homepage and it's the same one that the server can't access to.
How can I solve this problem?
If your home page is in the root change the code as below:
if (Session["username"] == null)
Response.Redirect("/HomePageWebSite.aspx");
The "/" in the beginning will always lookup from the root directory. If you do not give the "/" it will always lookup in the current directory which will results in problems if you have nested directories.

How to reload security principal user info or a partial view

I'm developing an aspnet mvc application and i have a problem to reload some data, i don't know if the problem is in the security principal info that every view contains or in my partial view that doesn't reload when some other view is shown.
I have a layout page that is used in my whole application, and inside this layout page i have this partial view code fragment:
#Html.Partial("_PartialActiveClient")
this partial view contains the next lines:
#if (User.IsInRole("HasClients"))
{
<p>An Active Client</p>
Change active client
}
else
{
<p>You don't have any clients<p>
Create client
}
So when a user creates an account for the first time, this user has 0 clients and doesn't belong to the "HasClients" role and the "you don't have any clients" message is shown, but when this user creates his first client, the user is added to the "HasClients" role by default in my controller. The problem is that the "you don't have any clients" is still there even if i change the views. In order for the other message to show, this user has to log out and then log in again.
So my question is, how can my users see the "An Active Client" message immediately after they create a client?
The roles are cached in a cookie , so you can force them to refresh by deleting the cookie. You need to refresh users role. Here is a ways
you can call this Roles.DeleteCookie(); and it will clear roles and reload it in the next request.
This is taken from this question page Refresh ASP.NET Role Provider
Just to clarify my comment to the answer provided by Tchaps. This is the code (not my original code, but make my point) to my solution, like i wrote in the comment, it's not elegant but i works, at least in my case.
// Add to role, save changes
await _userManager.AddToRoleAsync(userInSession.Id, roleHaveClients.Name);
await _userManager.UpdateAsync(userInSession);
// Sign out / Sing in
_registerManager.AuthenticationManager.SignOut();
await __registerManager.SignInAsync(userInSession, false, false);
// Redirect to another action
return RedirectToAction("someAction","someController");

How to direct to a member page from a non-member page when a user logs in?

I have two pages, NonMember.aspx and Member.aspx. If a user comes to the site, they will go to NonMember.aspx as soon as they login, I want them to immediately be redirected to Member.aspx, but instead of doing this, it is staying on NonMember.aspx. The user actually has to go click on the menu item again to get to Member.aspx.
The links are located at http://abc.com/tools/NonMember.aspx
and http://abc.com/tools/Member.aspx.
I was doing:
System.IO.Path.GetFileNameWithoutExtension(Request.Url.ToString());
but I am thinking there is a better way, especially since I have multiple default.aspx pages and this could pose a problem
Here is more detail on what exactly I am doing:
When I run the site on my local development machine, the NonMember page points to:
http://testserver/tools/NonMember.aspx.
Requet.Url.AbsolutePath points to /testserver/tools/NonMember.aspx.
Then I am doing this:
if(url == "~/tools/NonMember.aspx")
{
Response.Redirect("~/tools/Member.aspx");
}
The above is not working and I can check if url is equal to /testserver/tools/NonMember.aspx because if I deploy to liveserver, it will fail.
When using Forms Authentication for an ASP.NET application, it will automatically redirect you to the page you were viewing before you logged in. This is why you are redirected back to the NonMember.aspx page.
It would be better if you had just one member page, and perform a check in the page to see if the user is authenticated, if so, display the member content, otherwise, display the non-member content.
Then, when the user logs in and is redirected back to the page, they will see the member content.
If you are insistent on keeping the two separate pages, then in your check you simply have to see if the current user is authenticated (through the IsAuthenticated property on the User that is exposed through the page) and then redirect to your members page. If you are on the NonMember page, you don't need to check to see what the url is (unless this is MVC, which you didn't indicate).
If you have the HttpResponse object, you can use HttpResponse.Redirect
You should check your cookie or session variable to see if the user is logged in and then use a Response.Redirect to move them to the member page.
I'm not sure I get your scenario but, let's try.
If you have public pages, the login page and private pages (member pages) and once you authenticate your users you want them to browse ONLY the private part of your website, you should check early in the processing steps (AuthorizeRequest would be a good phase) if the request comming in is for a public or for the login page which you also consider public and redirect to your private page from there (like...having a "home" page for the member area of the site and always redirecting to it once you get an authenticated and properly authorized request to some public URL of your site).
EDIT: You should check for Request.FilePath
I ended up just doing the following:
if(Authenticated)
{
string path = Request.UrlReferrer.AbsolutePath;
if (path.EndsWith("/tools/NonMember.aspx"))
{
Response.Redirect("~/tools/Member.aspx");
}
}

Categories

Resources