MVC Area - How to Link to Root folder in BeginForm - asp.net-mvc

I need to define a link to LogOff controller which is in my Root shared folder; within BeginForm tag.
#using Microsoft.AspNet.Identity
#if (Request.IsAuthenticated) {
using (Html.BeginForm("", "", FormMethod.Post, new { id = "logoutForm", action = "Account/LogOff"}))
{
#Html.AntiForgeryToken()
#Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
#: | Log off
}
}
else {
#Html.ActionLink("Register", "Register", "Account")
#: |
#Html.ActionLink("Login", "Login", "Account")
}
Above works fine if I'm in root folder. But if clicked from Areas, it gives me The resource cannot be found error.
Requested URL: /MyApp/Area/Account/LogOff
The correct link should be /MyApp/Account/LogOff
I saw examples using #HTML.ActionLink but would prefer to keep define it in BeginForm, so the URL is not revealed to user.

I solved the problem with the following code.
First I mapped a route as follows
//Route config for logging off from areas.
routes.MapRoute(
name: "LogOff",
url: "Account/LogOff/",
defaults: new { controller = "Account", action = "LogOff" }
);
Then calling the route to logout, I used the following
#using (Html.BeginRouteForm("LogOff", FormMethod.Post, new { id = "logoutForm" })) {
#Html.AntiForgeryToken()
Log off
}

It may be easier to just add the Area routevalue to the BeginForm parameters. Leave it blank to point it to the root area, like this: new { Area = "" }
using (Html.BeginForm("LogOff", "Account", new { Area = "" }, FormMethod.Post, new { id = "logoutForm", #class = "navbar-right" }))
{
#Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right">
<li>Log off</li>
</ul>
}
This is using MVC 5

Related

How to return user information to View ASP.net MVC

My view's code[_LoginPartial.cshtml] is like below. I want to show more details like department. How to do it? I succeed in getting departments in IdentityModels.cs. But I don't know how to use it in view.
IdentityModels.cs
var directoryEntry = new System.DirectoryServices.DirectoryEntry();
var directorySearcher = new System.DirectoryServices.DirectorySearcher(directoryEntry);
directorySearcher.Filter = string.Format("(&(objectClass=user)(SamAccountName={0}))", mADUser.SamAccountName);
var result = directorySearcher.FindOne();
var entry = result.GetDirectoryEntry();
var (string)mADUserDirectoryEntry.Properties["department"].Value;
_LoginPartial.cshtml
#using Microsoft.AspNet.Identity
#if (Request.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Login", FormMethod.Post, new { id = "logoutForm", #class = "navbar-right" }))
{
#Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right">
<li>
#Html.ActionLink("Hi" + User.Identity.GetUserName(), "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage", #style = "color: white" })
ログオフ
</li>
<li></li>
</ul>
}
}
Since your View Model is of type Microsoft.AspNet.Identity you only have properties available that comes out of the box. Unless you extend the class.
Here is how you can do that: How to extend available properties of User.Identity
Then you will be able to use the department data as User.Identity.Department or User.Identity.GetDepartment().

Action link to absolute url (remove the ?) and keep the parameter

i'm trying to get an absolute url after sending a parameters from action link and I need it to be like
http://MySite/Controller/View/CityName
so I will be able to preform a search on the results page and no losing the first parameter (e.g.)
http://MySite/Controller/View/NewYork?Lecture=bobdillen
code :
#foreach (var city in #ViewBag.City)
{
#Html.ActionLink((string)#city, "LectureIn", new { #city }, null)
}
the action(LectureIn) code :
#using (Html.BeginForm("Search", "Lecture"))
{
<div class="form-group">
<div id="searchLecture" class="input-group">
#Html.TextBoxFor(m => m.SearchTerm, new { #class = "form-control", placeholder = "" })
<span class="input-group-addon">
<button type="submit"> <i class="glyphicon glyphicon-search"></i></button>
</span>
</div>
</div>
}
and in the controller :
public ActionResult LectureIn(string search = null)
{
// Do Staf
return View();
}
I have tried to change the routes but it didn't change
routes.MapRoute(
"lectureIn",
"{controller}/{action}/{id}",
new { controller = "TMaps", action = "lectureIn", City = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

MVC5 Web Application Scaffold - Account/Logoff - Why use HTTP Post?

I am trying to get my head around MVC 5 Web Application template, and I noticed that special attention is given to the security around the LogOff link.
In the scaffold template the "LogOff" link in the _LoginPartial.cshtml view sits inside an HTML form with an AntiForgeryToken in it, and is defined as a JS call to form's submit action, like so:
#if (Request.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", #class = "navbar-right" }))
{
#Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right">
<li>
#Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
</li>
<li>Log off</li>
</ul>
}
}
With the corresponding action method Account/LogOff inside ActionController defined like so:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
return RedirectToAction("Index", "Home");
}
My question is - what is the reasoning behind it? Why does the LogOff action require so much security protection? Why not just have this in the view,
#Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })
#Html.ActionLink("Log Off", "LogOff", "Account", routeValues: null, htmlAttributes: new { title = "LogOff" })
And this in the controller:
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
return RedirectToAction("Index", "Home");
}
What security hole would this create?
Thanks.
Please refer to this link: Logout: GET or POST?.
It will answer your question on why Post should be used in logout.

MVC "LogOut" controller causes "The resource cannot be found." error when using "ValidateAntiForgeryToken" attribute

When I add "ValidateAntiForgeryToken" attribute to my LoggOff controller, it doesn't map my controller and raises "The resource cannot be found." error. What is the problem? Here is my controller:
// POST
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
return RedirectToAction("Index", "Home");
}
Here is my view:
#using Microsoft.AspNet.Identity
#if (Request.IsAuthenticated)
{
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "__RequestVerificationToken", #class = "navbar-right" }))
{
#Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right">
<li>#Html.ActionLink("User: " + User.Identity.GetUserName(), "Manage", "Account", routeValues: null, htmlAttributes: new { title = "Manage" })</li>
<li>#Html.ActionLink("Log Off", "LogOff", "Account")</li>
</ul>
}
}
else
{
<ul class="nav navbar-nav navbar-right">
<li>#Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
<li>#Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}
you are not posting the form when you log off
this line will create a GET request
<li>#Html.ActionLink("Log Off", "LogOff", "Account")</li>
you need to add a submit button eg
Logout
Test this solution web.config, I had this problem and I had forgotten to uncomment tags

MVC Html.BeginForm using Areas

I'm using MVC areas and on a view that's in an area called "Test" I would like to have a form that posts to the following method:
area: Security
controller: AccountController
method: logon
How can I make this happen with Html.BeginForm? Can it be done?
For those of you that want to know how to get it to work with the default mvc4 template
#using (Html.BeginForm("LogOff", "Account", new { area = ""}, FormMethod.Post, new { id = "logoutForm" }))
Try this:
Html.BeginForm("logon", "Account", new {area="Security"})
Try specifying the area, controller, action as RouteValues
#using (Html.BeginForm( new { area = "security", controller = "account", action = "logon" } ))
{
...
}
Use this for area with HTML Attributes
#using (Html.BeginForm(
"Course",
"Assign",
new { area = "School" },
FormMethod.Get,
new { #class = "form_section", id = "form_course" }))
{
...
}
#using (Html.BeginForm("", "", FormMethod.Post, new { id = "logoutForm", action = "/Account/LogOff" }))
{#Html.AntiForgeryToken()
<a class="signout" href="javascript:document.getElementById('logoutForm').submit()">logout</a>
}
For Ajax BeginForm we can use this
Ajax.BeginForm("IndexSearch", "Upload", new { area = "CapacityPlan" }, new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = updateTarget }, new { id = "search-form", role = "search" })

Resources