This question already has answers here:
check if user is logged in in user control Asp.net MVC
(4 answers)
Closed 3 years ago.
So at the top of my controllers i've added in [Authorize],
So far so good only logged in users can access these pages (Person and Holiday)
However the tabs in the homeController which navigate the users to these pages are still displayed...coming from the layout.cs
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Person", "Index", "Person")</li>
<li>#Html.ActionLink("Holidays", "Index", "Holidays")</li>
How can I only get these tabs to display if a user is logged in.
I have tried the approach of adding in a bool in the AccountController.cs
else
{
loggedIn = true;
return RedirectToAction("Index", "Home");
}
}
else
{
loggedIn = false;
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
but then how do I access this from the layout.cs?
Is this the correct approach.
Please advise.
thanks
Please try this.
if (Request.IsAuthenticated)
{
//process here
}
else
{
// Response.Redirect("~/Login.aspx");
}
Related
I'm using ASP.NET MVC3. As of now I am restricting anonymous users to enter a particular page through
[Authorize]
in my controller. But what I want is to restrict them to view a tab in the main page if they are not log.in. Is this possible.? Sorry Im not pro in programming. :(
Yeah obcourse. You can do something like this
<li>#Html.ActionLink("Home", "Index", "Home")</li>
#if (Request.IsAuthenticated)
{
<li>#Html.ActionLink("View Account", "Index", "Account")</li>
if (User.IsInRole("Administrator"))
{
<li>#Html.ActionLink("Admin Console", "Index", "Admin")</li>
}
}
reference:Checking authentication and roles in a view
I have looked at many of the solutions on offer on this site and others for my problem but none of them seem to work perfectly for my solution.
On my Layout page I have a login area on the top of the screen. This is always present unless a user is logged in. This login form has a ValidationSummary on it and every time I post back using another form on the site the validation for this login form is being triggered.
I'm almost certain that this is down to how I call this login page from my Layout page. It is not a partial view that is in a Shared folder, it is in an Area in my project. On my Layout page I call the login form like this:
#Html.Action("LogOn", "Account", new { area = "Store" })
The logon page contains the following:
#model Project.ViewModels.LogOn_ViewModel
#{
Layout = null;
}
#using (Ajax.BeginForm("LogOn", "Account", new { #area = "Store" }, new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "LoginContainer", LoadingElementId = "actionLoaderImage" }, new { id="LogonForm" }))
{
#Html.AntiForgeryToken()
<div class="loginArea">
<div class="notRegistered">
<h4>Not registered yet?</h4>
Register now<br/>
#Html.ActionLink("Register", "Index", "SignUp", new { area = "Store" }, new { #class = "greenButton" })
</div> <!-- /notRegistered -->
<div class="loginForm">
<div class="formFields">
<label class="inline">#Html.LabelFor(m => m.UserName)</label>
#Html.TextBoxFor(m => m.UserName)
<label class="inline">#Html.LabelFor(m => m.Password)</label>
#Html.PasswordFor(m => m.Password)
<input type="submit" name="LogIn" value="Log in" class="blueButton" />
<img id="actionLoaderImage" src="#Url.Content("~/Content/web/images/loader.gif")" alt="icon" style="margin-right:15px; display:none;" />
#Html.ValidationSummary()
</div>
</div> <!-- /loginForm -->
</div> <!-- /loginArea -->
}
The login controller is standard stuff:
// GET: /Account/Logon
public ActionResult LogOn()
{
// if logged in show logged in view
if (User.Identity.IsAuthenticated)
return View("LoggedIn");
return View();
}
// POST: /Account/Logon
[HttpPost]
public ActionResult LogOn(LogOn_ViewModel model)
{
if (ModelState.IsValid)
{
if (SecurityService.Login(model.UserName, model.Password, model.RememberMe))
{
return View("LoggedIn");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
return PartialView(model);
}
I suspect that what is happening here is that Html.Action is 'posting' the login form if a post is occurring elsewhere on the page. This makes sense as the layout page itself would be posted as part of a form post action.
I tried implementing the custom Validator examples from some other SO questions and blogs (http://blogs.imeta.co.uk/MBest/archive/2010/01/19/833.aspx) but I found that using those examples would not display the validation summary with client side validation which is not much use to me.
The solution I am looking for would need to allow both client and server side validations to appear for the correct form. Does anyone have an example of something like this using MVC? I'd like to avoid manually looking after the client side validation using jquery if possible and just to use the framework to handle the work for me.
Thanks for your suggestions,
Rich
After playing around with this issue for longer than I care to admit, the answer as always was simple once you know how!
The solution to this issue for anyone else who comes up against it is to rename your action so your POST action is a different name to your GET action. This way, when the Layout page is posted back and triggers the PartialView to also be posted back there is only a GET action for your PartialView so the ValidationSummary will not be triggered.
Based on my example above I have altered the form to postback to another action for my login partial view and this has solved this issue for me.
In my Layout page the link to the partial in the store area remains the same:
#Html.Action("LogOn", "Account", new { area = "Store" })
The logon form action is then altered to point to a new action - not called the same name as the GET action:
#using (Ajax.BeginForm("ConfirmLogon", "Account", new { #area = "Store" }, new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "LoginContainer", LoadingElementId = "actionLoaderImage" }, new { id="LogonForm" }))
{
....
}
Then I just renamed my controller action so that it has a different action name for the POST action so that when the layout page is called using a post and the partial is loaded up with a POST action that it doesn't call my logon POST action:
// POST: /Account/ConfirmLogon
[HttpPost]
public ActionResult ConfirmLogon(LogOn_ViewModel model)
{
if (ModelState.IsValid)
{
if (SecurityService.Login(model.UserName, model.Password, model.RememberMe))
{
return PartialView("LoggedIn");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
return PartialView("Logon",model);
}
Hopefully this will help some others out with this issue. Seems so obvious now but drove me nutty :D
I am using ASP.NET, MVC3, Razor. In my site, I have login form on all pages (in the top header) from where the user can log in at anytime. The issue arises when another page with another form comes. I am not able to figure out how to implement that. I have tried a lot , but I think I need a very small example to solve my problem. The example can be as simple like a registration form and login form on the same page and they work separately, all their validations and other stuff. The login form and registration form can be partial views or anything that some one can suggest which is reusable.
Here's the code of _Register.cshtml(shared view)
#model MVCRnD.Models.RegisterModel
#using (Html.BeginForm("Register","Account")) {
}
Code for about.cshtml on which the above shared view was placed
#Html.Partial("_Register")
Code for Account Controller
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus createStatus;
Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
The partial view i.e. registration form is rendering fine. But when I click on submit button, it posts the whole form but take me to the register /Account/Register which is actually correct. But I want to be on same page and does not go to the other form. Do you want me to send the full code ? I can upload it somewhere and send you the link.
Not sure why you're having problems, but putting two forms on the same page is a very common practice regardless of what server-side language you use.
#using (Html.BeginForm("Logon", "Account")) {
...
}
#using (Html.BeginForm("Register", "Account")) {
...
}
Which translates to:
<form action="/Account/Logon" method="post">
...
</form>
<form action="/Account/Register" method="post">
...
</form>
In my view I disable or enable links as below. Even if the link "Insured or Owner Name Change" is disabled in the view I am able to access it through the url like "http://localhost:0000/NameChangeRequest?contract=111111" which should not be happening. Can anyone help me on this?
#if (Model.CanCreateNameChangeRequest)
{
#Html.ActionLink("Insured or Owner Name Change", "Index", "NameChangeRequest", new { #contract = Model.ContractNumber }, new { #class = "requestLink" });
}
else
{
<span class="requestLinkDisabled">Insured or Owner Name Change</span>
}
You should never use Views to handle access control or any nature of business logic really. The View should only have presentation layer logic and markup.
That said, you can do this in the "NameChangeRequestController" -> "Index" action:
public ActionResult Index()
{
if(!Model.CanCreateNameChangeRequest)
RedirectToAction("Index","Home");
}
Also, this looks a lot like Role based permissions, in which case you should use the "[Authorize]" attribute along with "IsInRole".
I'm using Asp.Net MVC 3 (with Razor) and jQuery/jQueryUI to create a dialog login box.
I'm still quite new to these technologies and have run into a problem.
The login form is in a partial view, I use the following jQuery code to load it into the page:
$('#log-in').click(function () {
if (ServerModel.UserId == 0) {//User not logged in, open login dialog
$("<div></div>")
.addClass("dialog")
.addClass("form-dialog")
.attr("id", "login-dialog")
.appendTo("body")
.dialog({
title: 'LOGIN',
close: function () { $(this).remove() },
modal: true,
width: 323,
resizable: false
})
.load(ActionUrls.LogOn);
}
});
ActionUrls.LogOn, has the path for the Logon action method in the controller.
The partial view with the login form looks along these lines:
#using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "login-dialog" }))
{
//Login form fileds in here with submit button at the end
}
Here's the code for the controller:
[HttpGet]
public ActionResult LogOn()
{
return PartialView("_Logon");
}
[HttpPost]
public ActionResult LogOn(LogOnModel model)
{
if (ModelState.IsValid)
{
CustomSqlMembershipProvider provider = new CustomSqlMembershipProvider();
if (provider.ValidateUser(model.UserName, Security.ComputeHash(model.Password)))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// something failed, redisplay partial view with the model
return PartialView("_Logon", model);
}
This all works fine, however the problem I'm having, is that when the user is authenticated, as can be seen in the controller code. I try to RedirectToAction("Index", "Home"), this with the intent that the page should reload with the user logged in and the dialog closed.
However at the moment, just the login dialog box reloads with the whole page content in it. I understand that this is probably normal behavior, as I'm telling the form in the logon view to update the UpdateTargetId of the dialog box.
So the question is, can I reach my desired result of the whole page reloading and if so, how??
Any help and hints would be most appreciated.
/Ola
Instead of using a form parameter you can use jquerys ajax method and send in the username and password and in the success function of the ajax method if the user is successfully authenticated redirect the user to your index page.
note the index page should still have a way to determine that the user is authenticated or not else anyone can typein the url.
What do you think?
On your .load ajax call, the data that is returned contains redirect information. I'm not sure if this is only for JSON POSTS, but it's worth a try:
...
.load(ActionUrls.LogOn, function(data) {
if (data.redirect) {
window.location.href = data.redirect;
else {
// other
}
});
Update:
The callback event that you need to hook onto is the one that submits the login information, not the one that loads the login page. I asked you to hook onto the wrong ajax call on top, the one you need to latch onto is this one:
#using (Ajax.BeginForm(new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "login-dialog" }))
{
//Login form fileds in here with submit button at the end
}
Unfortunately, I do not know how to hook onto that event. This article may help:
How to get an ASP.NET MVC Ajax response to redirect to new page instead of inserting view into UpdateTargetId?
I noticed it's an old question, but I hope my reply may help to someone.
For something similar I redirected to a 'helper' page in the controller action, which contained (for me almost) only some JavaScript in the scipt tag (or you should link it of course).
In this case that's enough:
window.location.href = "http://www.foo.com";
...and I also find and close the dialog there:
$('#login-dialog').dialog('close');
For me it was well, but I also appreciate better solutions.