unable to call LogOff method in controller - asp.net-mvc

I have started a project using MVC6 and can't seem to route to the LogOff method.
The account controller looks like this:
//
// POST: /Account/LogOff
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LogOff()
{
await _signInManager.SignOutAsync();
_logger.LogInformation(4, "User logged out.");
return RedirectToAction(nameof(HomeController.Index), "Home");
}
The calling navigation looks like this:
#if (User.IsSignedIn())
{
<div class="profile-picture">
<div class="stats-label text-color">
<span class="font-extra-bold font-uppercase">#User.GetUserName()</span>
<div class="dropdown">
<a class="dropdown-toggle" href="#" data-toggle="dropdown">
<small class="text-muted">Title <b class="caret"></b></small>
</a>
<ul class="dropdown-menu animated flipInX m-t-xs">
<li>Log off</li>
<li>Link 2</li>
<li>Link 3</li>
</ul>
</div>
</div>
</div>
}
I have applied a break point in the on the first line of the method in the controller however it never breaks on it and the browser just goes blank.
What am I doing wrong?

Instead of
<li>Log off</li>
Try replacing like this:
#using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" }))
{
#Html.AntiForgeryToken()
<li>Log off</li>
}

Related

Why does HttpContext.User.Identity.Name contain the wrong name?

I have a .NET 5 MVC application that periodically checks access based on the HttpContext.User.Identity.Name value. The app uses Azure AD. Sometimes as I switch between users (Signing out and Signing in), the HttpContext.User.Identity.Name value will contain the previous user's name and the current user will have the access of the previous user.
Even more strange is the the login shown is correct.
This is just the boiler plate code generated by visual studio:
#using System.Security.Principal
<ul class="navbar-nav">
#if (User.Identity.IsAuthenticated)
{
<li class="nav-item">
<span class="navbar-text text-light">Hello #User.Identity.Name!</span>
</li>
<li class="nav-item">
<a class="nav-link text-light" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignOut">Sign out</a>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-light" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignIn">Sign in</a>
</li>
}
</ul>
So #User.Identity.Name on the .cshtml is always correct, but HttpContext.User.Identity.Name on the controller is the previous (cached?) user.
Any clues to why the previous user gets cached?
Here is a sample of how I call it on the controller:
ViewData["User"] = HttpContext.User;
ViewData["Menu"] = await _menuService.GetReportMenuAsync(MenuService.ReportMenuItemOption.Genesis01, User.Identity.Name);
var userAccess = await _userAccessService.GetUserEntityAccessAsync(User.Identity.Name);
var model = new SomeModel
{
SearchDate = DateTime.Now.AddDays(-7),
Banks = userAccess.Banks,
ATMIds = userAccess.ATMs
};
return View(model);
This is in my StartUp:
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI();

ASP.NET MVC: How do I link correctly to my Delete method using Html.BeginForm?

So far I came up with this:
<ul class="menu" id="#Model[i].VideoId">
<li class="menu-item">
#using (Html.BeginForm("Delete", "Video", FormMethod.Post, new { id = Model[i].Id }))
{
#Html.HttpMethodOverride(HttpVerbs.Delete)
<button class="btn btn-link" type="submit">Delete</button>
}
</li>
<li class="menu-item">Edit </li>
</ul>
But it doesn't work. My controller is Video and the method is Delete, which takes an id parameter and deletes by id from the database.

Redirect to another page from _Layout.cshtml

How to redirect to another page within the _layout.cshtm page in asp.net core razor.
I am doing the verification and user is logged in, if not it will be redirected to another page.
#using Microsoft.AspNetCore.Identity
#using CronoParque.Model
#inject SignInManager<ApplicationUser> SignInManager
#inject UserManager<ApplicationUser> UserManager
#if (SignInManager.IsSignedIn(User))
{
<form asp-controller="Account" asp-action="Logout" method="post" id="logoutForm" class="navbar-right">
<ul class="nav navbar-nav navbar-right">
<li>
<a asp-page="/Account/Manage/Index" title="Manage">Ola #UserManager.GetUserName(User)!</a>
</li>
<li>
<button type="submit" class="btn btn-link navbar-btn navbar-link">Sair</button>
</li>
</ul>
</form>
}
else
{
// targeting here
}
Answer
#if (SignInManager.IsSignedIn(User))
{
// normal stuff
}
else if (!Context.Request.Path.ToString().Contains("/About"))
{
// If we aren't processing a request for the target page,
// then redirect to it.
Context.Response.Redirect("/About");
}
Maybe a Better Answer
The use case for your question might be to redirect unauthorized requests to a log in page. In that case, use the built-in razor pages authorization API.
services
.AddMvc()
.AddRazorPagesOptions(options => {
options.Conventions.AuthorizePage("/Contact");
});
The above code goes into the Startup > ConfigureServices method.
In the above example, the API redirects unauthorized requests for the /Contact.
See also: https://learn.microsoft.com/en-us/aspnet/core/security/authorization/razor-pages-authorization?view=aspnetcore-2.1#require-authorization-to-access-a-page

ASP.net MVC unable to call POST Logout method

I've been trying to perform Logout operation (Form Authentication with cookies) but unable to call the POST Logout action method.
Here's my Partial View:
<nav class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="nav navbar-nav navbar-right">
#using (Html.BeginForm("Logoff", "Account", FormMethod.Post, new { id = "logoutForm" }))
{
#Html.AntiForgeryToken()
<a class="navbar-brand" href="javascript:document.getElementById('logoutForm').submit()" title="Logout">
<img alt="Home" src="#Url.Content(" ~/Images/logout.png ")"/>
</a>
}
</div>
</div>
</nav>
I'm calling this partial View in below Home page as header:
<header role="banner">
#Html.Partial("_HomeHeader")
</header>
<div class="container">
.......
</div>
In my account controller, I've defined following action method:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Logoff()
{
FormsAuthentication.SignOut();
Session.Clear();
return Redirect(FormsAuthentication.LoginUrl);
}
Thus, on clicking the Logout button from the home page, it should Go to the "Logoff" action method and clear the cookies and then redirect to Login Page.
But it doesn't work.
Instead, it goes to the Login page directly without visiting the Logoff action method. I got this URL:
http://localhost/Account/Login?ReturnUrl=%2FAccount%2FLogoff
Can anyone please provide their inputs regarding how to achieve this functionality?
I know you already far in the process but you could use the WebSecurity method instead of your action method in your action controller... (OathWebsecurity, WebSecurity.Logout();... etc)
Try the below code, Hope it Helps.!
<a class="navbar-brand" href="javascript:submitform()" title="Logout">
<img alt="Home" src="#Url.Content(" ~/Images/logout.png ")"/>
</a>
<script type="text/javascript">
function submitform()
{
$("#logoutForm").submit();
}
</script>

Trying to create drop down login for Orchard CMS

I am new to Orchard and to ASP.NET MVC. I am trying to override the login process for users so that instead of going to a dedicated login page (the default process) they get a drop down form from the user menu that logs them in. I have created overrides in my custom theme for LogOn.cshtml and User.cshtml. The code is as follows:
//User.cshtml
#using System.Web.Mvc;
#using Orchard.ContentManagement;
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<ul class="nav navbar-nav pull-right">
#if (WorkContext.CurrentUser != null) {
<li class="dropdown">
<button id="userDropdown" class="btn btn-primary navbar-btn dropdown-toggle" data-toggle="dropdown">
Welcome #Html.ItemDisplayText(WorkContext.CurrentUser) <span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>
#Html.ActionLink(T("Change Password").ToString(), "ChangePassword", new { Controller = "Account", Area = "Orchard.Users" })
</li>
<li>
#Html.ActionLink(T("Sign Out").ToString(), "LogOff", new { Controller = "Account", Area = "Orchard.Users", ReturnUrl = Context.Request.RawUrl }, new { rel = "nofollow" })
</li>
#if (AuthorizedFor(Orchard.Security.StandardPermissions.AccessAdminPanel)) {
<li class="divider"></li>
<li>
#Html.ActionLink(T("Dashboard").ToString(), "Index", new { Area = "Dashboard", Controller = "Admin" })
</li>
}
</ul>
</li>
}
else {
<li class="dropdown">
<button class="btn btn-primary navbar-btn dropdown-toggle" data-toggle="dropdown">
Sign In <span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li>
#Display.LogOn()
</li>
</ul>
</li>
}
</ul>
</div>
//LogOn.cshtml
#using System.Web.Mvc;
#using Orchard.ContentManagement;
<div>
#using (Html.BeginFormAntiForgeryPost(Url.Action("LogOn", new { ReturnUrl = Request.QueryString["ReturnUrl"] }))) {
<fieldset class="login-form group">
<legend>#T("Account Information")</legend>
<div class="form-group">
<label for="username-email">#T("Username")</label>
#Html.TextBox("userNameOrEmail", "", new { id = "username-email", autofocus = "autofocus", #class = "validate[required]" })
#Html.ValidationMessage("userNameOrEmail")
</div>
<div class="form-group">
<label for="password">#T("Password")</label>
#Html.Password("password", null, new { #class = "validate[required]" })
#Html.ValidationMessage("password")
</div>
<div class="checkbox">
<label class="forcheckbox" for="remember-me">
#Html.CheckBox("rememberMe", new { id = "remember-me" }) #T("Remember Me")
</label>
</div>
<div class="form-group">
<button class="primaryAction" type="submit">#T("Sign In")</button>
</div>
</fieldset>
}
</div>
The form displays fine in the dropdown, but when the submit button is clicked, I get a HTTP 404 error: Requested URL: /OrchardLocal/Contents/Item/LogOn.
I'm afraid that the default login process requires a separate view. I've been trying to figure out which existing override to use, but I'm just not seeing it. Any help would be greatly appreciated. Thanks.
You should be able to login properly by changing your form from
#using (Html.BeginFormAntiForgeryPost(Url.Action("LogOn", new { ReturnUrl = Request.QueryString["ReturnUrl"] })))
to something like this:
#using ( Html.BeginForm("LogOn", "Account", new { area = "Orchard.Users" /*other route values here*/ }, FormMethod.Post) )
{
#Html.AntiForgeryToken()
// ... your stuff here
}
This is the same for every other controller action. If in doubt: specify the area explicitly.

Resources