ASP.net MVC unable to call POST Logout method - asp.net-mvc

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>

Related

How to get the dynamic data of fragment to another page using thymelleaf

I want to get the information(which is dynamically generated) from one html page into another html page.
I used a tag th:fragment in first html page and th:replace in second html page.
But i am getting only static content of first page, is it possible to get the dynamic data or not? can anyone help me please.
Thanks in advance.
Here is my Java code :
#Controller
public class WelcomeController {
#RequestMapping("/")
public ModelAndView usingToList(Model model) {
List<String> colors = new ArrayList<>();
colors.add("green");
colors.add("yellow");
colors.add("red");
colors.add("blue");
model.addAttribute("message", "harika");
model.addAttribute("colors", colors);
List<String> colors2 = new ArrayList<>();
colors2.add("pinkish");
colors2.add("green");
colors2.add("yellow");
colors2.add("red");
colors2.add("blue");
model.addAttribute("coloring", colors2);
ModelAndView mv = new ModelAndView();
mv.setViewName("welcome");
return mv;
}
#GetMapping("/toList")
public String usingToList2(Model model,String color) {
System.out.println("inside uselist");
List<String> colors2 = new ArrayList<>();
if(color.equals("pinkish"))
{
colors2.add("pinkish");
colors2.add("amity");
colors2.add("pimity");
}
if(color.equals("green"))
{
colors2.add("greenish");
colors2.add("amity");
colors2.add("Pretty");
}
model.addAttribute("colors", colors2);
return "welcome";
}
}
Below is my sample POC :
here is my fragment: nav.html which it load the colors dynamically. I am using this side bar fragment in all the pages. When I go another page, data in the side bar is disappering.
<div th:fragment="sidebar2">
<div class="sidebar-sticky pt-3">
<ul class="nav flex-column" id="accordionSidebar">
<li class="nav-item">
<a type="button"
id="collapse"
data-toggle="collapse"
data-target="#collapseExample"
aria-expanded="false" aria-
controls="collapseExample">
<span class="menu-title">Colors List</span>
<span data-feather="plus-circle"></span>
</a>
<div class="collapse" id="collapseExample">
<ul class="nav flex-column sub-menu"
id="collapseExample2">
<li th:each="color :
${coloring}">
<a th:href="#{/toList(color=${color})}"
th:text="${color}"> ></a>
</li>
</ul>
</div>
</div>
welcome.html:
<div th:replace="fragments/nav :: sidebar2"></div>
<main role="main" class="container">
<div class="starter-template">
<h1>Spring Boot Web Thymeleaf Example</h1>
<h2>
<span th:text="'Hello, ' + ${message}"></span>
</h2>
</div>
<ol>
<li th:each="color2 : ${colors}" th:text="${color2}"></li>
</ol>
</main>
When you navigate from one page to another, the Model is empty again (unless you are doing a <form> POST).
When you show the welcome.html Thymeleaf template via usingToList2(), then there is nothing in the Model for the coloring key.
To solve it, also add the coloring key in the usingToList2() controller method.
UPDATE: If all controllers need it, you can use #ControllerAdvice:
#ControllerAdvice
public class GlobalControllerAdvice {
#ModelAttribute("coloring")
public List<String> coloring() {
List<String> colors2 = new ArrayList<>();
colors2.add("pinkish");
colors2.add("green");
colors2.add("yellow");
colors2.add("red");
colors2.add("blue");
}
}
Or if all methods in a single controller need it, you can just add that method in the controller class itself.

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

How to keep navbar on ProductList Page

I am working on my MVCOnlineShop, i made on the homepage on the navbar a dropdownlist with categories as dropdown button and products as dropdowncontent, i want to keep this on the ProductList View:
this is my CategoryLayout.cshtml(PartialView):
#model IEnumerable<MVCOnlineShop.Models.Category>
#{
ViewBag.Title = "CategoryLayout";
}
#foreach (var Category in Model)
{
<li>
<div class="dropdown">
<button class="dropbtn">
#Html.ActionLink(Category.CategoryName,
"ProductList", new { Category = Category.CategoryID }, new { #style = "color:#1ABC9C;text-decoration:none;" })
</button>
<div class="dropdown-content">
#foreach (var Product in Category.Products)
{
#Html.ActionLink(Product.ProductName,
"Details", new { id = Product.CategoryID }, new { style = "text-decoration:none;" })
}
</div>
</div>
</li>
}
this is my ProductList.cshtml PartialView:
#model MVCOnlineShop.Models.Category
#{
ViewBag.Title = "ProductList";
}
<script src="~/Scripts/Productjs/bootstrap.min.js"></script>
<script src="~/Scripts/Productjs/jquery.js"></script>
<link href="~/Content/Productcss/bootstrap.min.css" rel="stylesheet">
<link href="~/Content/Productcss/2-col-portfolio.css" rel="stylesheet">
<div class="container">
<!-- Page Header -->
<div class="row">
#foreach (var Product in Model.Products)
{
<div class="col-md-6 portfolio-item">
<a href="#">
<img class="img-responsive" src="#Product.ImageID" alt="">
</a>
<h3>
#Html.ActionLink(Product.ProductName, "Details", new { id = Product.CategoryID })
</h3>
</div>
}
</div>
</div>
and this is how i rendered the CategoryLayout.cshtml in the _Layout.cshtml to show the dropdownlist on the homepage:
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
#Html.Partial("CategoryLayout")
</ul>
</div>
</div>
</div>
Question: how to show this navbar on the ProductList too?
Thanks in advance!
Create a child action:
[ChildActionOnly]
public ActionResult Navbar()
{
var categories = // get categories;
return PartialView("_Navbar", categories);
}
Then, create a partial view to render the navbar (_Navbar.cshtml):
#model IEnumerable<MVCOnlineShop.Models.Category>
#foreach (var Category in Model)
{
<li>
<div class="dropdown">
<button class="dropbtn">
#Html.ActionLink(Category.CategoryName, "ProductList", new { Category = Category.CategoryID }, new { #style = "color:#1ABC9C;text-decoration:none;" })
</button>
<div class="dropdown-content">
#foreach (var Product in Category.Products)
{
#Html.ActionLink(Product.ProductName, "Details", new { id = Product.CategoryID }, new { style = "text-decoration:none;" })
}
</div>
</div>
</li>
}
Then, call the following where you want the navbar to appear:
#Html.Action("Navbar", "Foo")
Where "Foo" is the name of the controller where you added the child action. Then, the view can use whatever model it needs to you and you can still render your navbar with its own model.
If I understood I think what you are looking for is a master page
MSDN says :
ASP.NET master pages allow you to create a consistent layout for the pages in your application. A single master page defines the look and feel and standard behavior that you want for all of the pages (or a group of pages) in your application.
Notice the part saying : standard behavior that you want for all of the pages ...in your application
So what you'll do is rethink your approach. Every element that must appear on every page is to be defined in the master page view.
Please read this MSDN article about creating a master page and child pages
Simply, this is how your master page should be :
<%# Master Language="C#" AutoEventWireup="true" CodeFile="you_file_name.cs" Inherits="Site" %>
<html>
<head>
<asp:ContentPlaceHolder ID="head" runat="server"></asp:ContentPlaceHolder>
<!-- some other elements like scripts, css, etc...-->
</head>
<body>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">#Html.Partial("CategoryLayout")</ul>
</div>
<!-- Here add the code for rendering any other view at will ; for instance ProductList -->
</body>
</html>
Becarefull though : ALL other views that you want to render inside the master page will have to be created accordingly (create view content with master page... and select the appropriate master page on view creation dialog)

unable to call LogOff method in controller

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>
}

ASP.NET MVC connect buttons to methods in controller

I have two buttons in my view and I want to add some information to my database when user click each of these two buttons.
<div class="container">
<div class="btn-group" style="text-align: center">
<h2>
<font color="gray">Please Choose your Department</font></h2>
<div class="btn-toolbar pagination-centered">
<div class="btn-group">
<button id="SARU" class="btn btn-inverse btn-large">
SARU</button>
<div class="span1">
<button id="AN" class="btn btn-inverse :hover btn-large">
AN</button>
</div>
<script type="text/javascript">
$('#SARU').click(function () {
UserController.AddGroupSARU();
});
$('#AN').click(function () {
UserController.AddGroupAN();
});
</script>
</div>
</div>
</div>
and the AddGroupSARU and AddGroupAN methods are in Usercontroller . how should I do this ?
Use jquery ajax to make a call to the action method. You can use the $.post method.
$(function(){
$('#SARU').click(function () {
$.post("#Url.Action("AddGroupSARU","User")");
});
});
The Url.Action helper method will resolve the proper path to the action method and render it. If you look at the View source of the page you will see the js code like
$(function(){
$('#SARU').click(function () {
$.post("User/AddGroupSARU");
});
});
Decorate your action method with [HttpPost] attribute as well. It is a good idea to keep your data updation/insertion/DELETION operations in a HttpPost action method so that boats/search engine won't destroy your data.
[HttpPost]
public ActionResult AddGroupSARU()
{
// do something and return something
}
u can use Jquery and ajax. i try to use Razor to connect button to methods in controller
like this..
<input style="width:100px;" type="button" title="EditHotelDetail" value="EditDetails" onclick="location.href='#Url.Action("Edit", "Hotel")'" />
"Edit" is name of your methods
"Hotel" is name of your controller

Resources