How to Change Route to Username After Logged In

How to change route to username after logged in?

You need to add a route to cover the case that has a user name.

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
name: "Username_Default",
url: "{username}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { username = new OwinUsernameConstraint() }
);

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}

But for that to work right, you will either need to add a literal string to your URL to identify the segment as username (i.e. username-{username}\) or you will need to make a constraint that only allows the user names that are in the database. Here is an example of the latter:

using MvcUsernameInUrl.Models;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.Routing;

namespace MvcUsernameInUrl
{
public class OwinUsernameConstraint : IRouteConstraint
{
private object synclock = new object();

public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
if (parameterName == null)
throw new ArgumentNullException("parameterName");
if (values == null)
throw new ArgumentNullException("values");

object value;
if (values.TryGetValue(parameterName, out value) && value != null)
{
string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
return this.GetUsernameList(httpContext).Contains(valueString);
}
return false;
}

private IEnumerable<string> GetUsernameList(HttpContextBase httpContext)
{
string key = "UsernameConstraint.GetUsernameList";
var usernames = httpContext.Cache[key];
if (usernames == null)
{
lock (synclock)
{
usernames = httpContext.Cache[key];
if (usernames == null)
{
// Retrieve the list of usernames from the database
using (var db = ApplicationDbContext.Create())
{
usernames = (from users in db.Users
select users.UserName).ToList();
}

httpContext.Cache.Insert(
key: key,
value: usernames,
dependencies: null,
absoluteExpiration: Cache.NoAbsoluteExpiration,
slidingExpiration: TimeSpan.FromSeconds(15),
priority: CacheItemPriority.NotRemovable,
onRemoveCallback: null);
}
}
}

return (IEnumerable<string>)usernames;
}
}
}

NOTE: I strongly recommend using caching for this as in the example, since route constraints run on every request and it is not good to hit the database on every request. The downside of this is that it takes up to 15 seconds for the username to become active after it is registered. You could potentially get around this by updating the cache (in a thread-safe way) when a new account is registered in addition to adding the record to the database, which would make it available immediately in the route constraint.

Then it is simply a matter of doing a 302 redirect when the user logs in. You could potentially do that in a global filter.

using System.Web;
using System.Web.Mvc;

namespace MvcUsernameInUrl
{
public class RedirectLoggedOnUserFilter : IActionFilter
{
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var routeValues = filterContext.RequestContext.RouteData.Values;
bool isLoggedIn = filterContext.HttpContext.User.Identity.IsAuthenticated;
bool requestHasUserName = routeValues.ContainsKey("username");

if (isLoggedIn && !requestHasUserName)
{
var userName = filterContext.HttpContext.User.Identity.Name;
// Add the user name as a route value
routeValues.Add("username", userName);

filterContext.Result = new RedirectToRouteResult(routeValues);
}
else if (!isLoggedIn && requestHasUserName)
{
// Remove the user name as a route value
routeValues.Remove("username");

filterContext.Result = new RedirectToRouteResult(routeValues);
}
}

public void OnActionExecuted(ActionExecutedContext filterContext)
{
// Do nothing
}
}
}

Usage

public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new RedirectLoggedOnUserFilter());
filters.Add(new HandleErrorAttribute());
}
}

MVC will automatically reuse route values from the request when genrating URLs, so there is no need to change any of your ActionLinks to include username.

Here is a working demo on GitHub using MVC5, OWIN, and ASP.NET Identity.

MVC Application Username in route upon login

I believe it should be something like this:

routes.MapRoute(
name: "UserNameRoute",
url: "Dashboard/User/{username}",
defaults: new { username = "" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

I chose not to put the {controller} and {action} placeholders in the template as that would make it equal to the default route template. You could of course use just the action template if that is what you need:

routes.MapRoute(
name: "UserNameRoute",
url: "Dashboard/{action}/{username}",
defaults: new { action = "User", username = "" }
);

Also note I put it before the default route because it is more specific. Otherwise the default route would catch every request.

Authorization is something you can't do here however. You will need to do that by e.g. creating a custom AuthorizeAttribute subclass that checks the username matches the logged in user.

Where to change route '/home' when user is login and try to login again in laravel

In RedirectIfAuthenticated in the App\Http\Middleware folder:

public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/home');
}

return $next($request);
}

So change the redirect('/home'); to where ever you want it to redirect.

Routing in ASP.NET MVC, showing username in URL

On its own, your routing will not work because if the url was .../Product meaning that you wanted to navigate to the Index() method of ProductController, it would match your first route (and assume "Product" is the username. You need to add a route constraint to your roue definitions that returns true if the username is valid and false if not (in which case it will try the following routes to find a match).

Assuming you have a UserController with the following methods

// match http://..../Bryan
public ActionResult Index(string username)
{
// displays the home page for a user
}

// match http://..../Bryan/Photos
public ActionResult Photos(string username)
{
// displays a users photos
}

Then you route definitions need to be

public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "User",
url: "{username}",
defaults: new { controller = "User", action = "Index" },
constraints: new { username = new UserNameConstraint() }
);
routes.MapRoute(
name: "UserPhotos",
url: "{username}/Photos",
defaults: new { controller = "User", action = "Photos" },
constraints: new { username = new UserNameConstraint() }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Test", action = "Index", id = UrlParameter.Optional }
);
}

public class UserNameConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
List<string> users = new List<string>() { "Bryan", "Stephen" };
// Get the username from the url
var username = values["username"].ToString().ToLower();
// Check for a match (assumes case insensitive)
return users.Any(x => x.ToLower() == username);
}
}
}

If the url is .../Bryan, it will match the User route and you will execute the Index() method in UserController (and the value of username will be "Bryan")

If the url is .../Stephen/Photos, it will match the UserPhotos route and you will execute the Photos() method in UserController (and the value of username will be "Stephen")

If the url is .../Product/Details/4, then the route constraint will return false for the first 2 route definitions and you will execute the Details() method of ProductController

If the url is .../Peter or .../Peter/Photos and there is no user with username = "Peter" then it will return 404 Not Found

Note that the the sample code above hard codes the users, but in reality you will call a service that returns a collection containing the valid user names. To avoid hitting the database each request, you should consider using MemoryCache to cache the collection. The code would first check if it exists, and if not populate it, then check if the collection contains the username. You would also need to ensure that the cache was invalidated if a new user was added.

How to change login route name

You could write the routes yourself inside your routes/web.php file:

Route::get('user', 'Auth\LoginController@showLoginForm');
Route::get('new-user', 'Auth\RegisterController@showRegistrationForm');

These will be created next to your original login routes if you use Auth::routes(); inside your routes/web.php.

If you want to remove the Auth::routes(); you can offcourse, but you will have to add the post methods as well from the original login routes. You can check where they are going by doing php artisan route:list in your terminal to figure out how to point these and to which method.

rendering username or id in the url with express routing

When you define the profile router in your main server file, instead of defining one specific route, define a short prefix. In your case you'll use /profile. Then in your router simply define the rest of the route (/:id).

Example:

Server:

app.use("/profile", profile, (req, res, next) => {
next();
});

Router:

router
.route("/:id")
.get(function (req, res) {
if (req.isAuthenticated()) {
let dateObj = req.user.createdAt;
let createdDate = dateObj.toString().slice(4, 16);
let navbarLoggedIn = "partials/loggedIn-navbar.ejs";
let id = req.params.username;
console.log(id + "\n");
res.render(
"profile",
{
id: req.params.id
},
{
currentUser: req.user.username,
currentCompany: req.user.company,
currentLocation: req.user.location,
currentPosition: req.user.position,
memberStatus: createdDate,
navbar: navbarLoggedIn,
}
);
} else {
res.redirect("login");
}
});

How to customize route config if user already logged in asp mvc 5

Public ActionResult Index()
{
If(user is logged in already)
{
Return RedirectToAction("dashboard","manage");
}
// code something
}

Write RedirecttoAction method in Home controller index action for navigate to other webpage.

how do we pass the user id into a route in app.js?

you can create a file for auth context then create a context and export it

export const AuthContext= React.createContext({userId:"",setUserId: ()=>{}}); //the param here should be the default value (default shape of the object you wanna pass to children)

Then in your app.js import that context and wrap your other components with

const [userId, setUserId] = useState("");

<AuthContext.Provider value={{userId:userId, setUserId:setUserId}}> //the object contains the state or functions you wanna access from child components
//your other components
</AuthContext.Provider>

now inside any screen or component that needs to access or set the user id (or any other value or callback you passed) you can just import the context and access the value like this

const {userId,setUserId} = useContext(AuthContext)

you can also refer to this example:

https://fatmali.medium.com/use-context-and-custom-hooks-to-share-user-state-across-your-react-app-ad7476baaf32



Related Topics



Leave a reply



Submit