ASP.Net MVC3 Controller Authorize attribute issue - asp.net-mvc-3

I have a Home Controller with these actions:
public class HomeController : Controller
{
[Authorize]
public ActionResult Index()
{
return View();
}
public ActionResult Logoff()
{
HttpContext.Session.Remove("LogonTicket");
HttpContext.Session.Remove("PID");
return View("Index");
}
Now, when I logoff using the Logoff Action, I want the Authorize attribute of the Index to take effect but it doesn't when I return the Index View in the Logoff Action.
How would I handle this?
I'm using a custom MembershipProvider and not sure how to put Logoff functionality in it.

You should redirect, not return the view directly:
public ActionResult Logoff()
{
HttpContext.Session.Remove("LogonTicket");
HttpContext.Session.Remove("PID");
return RedirectToAction("Index");
}
Returning the view directly sends the view's markup to the client right away and the Authorize filter does not get invoked at all.

Done in the AccountController Logoff Action. They are public "globals" in a base controller now, too.
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
LogonTicket = null;
ParticipantID = null;
return RedirectToAction("Index", "Home");
}

Related

Can I write my own view in asp mvc 3 razor?

Usually I have a simillar code with this
puclic class FooController{
public ActionResult Index(){
return View(DbContext.Foo.ToList());
}
public ActionResult Create(){
return View(new FooModel());
}
}
I want to replace return View(new FooModel()); with return MyView(new FooModel()) where MyView has more attributes than View class.
View() essentially instantiates an instance of ViewResult, so yes, you can define a method MyView() which instantiates a custom instance of ViewResult with more parameters.

ActionResult HttpPost need to access value

I am using MVC C#
Say I have the following ActionResult:
public ActionResult Create(string location)
{
...
View()
}
I need to use location primary in the [httppost]
[HttpPost]
public ActionResult Create(Employee employee)
{
...
// I need to access the value of location here but I dont' have access to the View
}
What is the best way of getting the value of location. I can create a viewmodel and pass that value to the View and then retreive it in the [HttpPost ]but I do not have access to the View as it is restricted.
There is a number of methods to pass data between controller methods in mvc. One of them is by using TempData.
You can save location in your GET-method
public ActionResult Create(string location)
{
TempData["location"] = location;
...
View()
}
and then retrieve it in your POST-method
[HttpPost]
public ActionResult Create(Employee employee)
{
var location = TempData["location"];
...
}
Although, using a viewmodel would be more preferrable.

Override controller Authorize attribute for viewresult

If the authorize attribute has been applied to the controller is it possible to allow unauthorized access to an action/viewresult inside that controller?
Say for example I didn't want authorization to occur on Test2 in the following:
[Authorize]
public class TestController : Controller
{
public ViewResult Test()
{
return View();
}
public ViewResult Test2()
{
return View();
}
}
Thanks in advance.
No, this is not possible. You will have to apply the Authorize attribute on the Test action and not on the controller. Another possibility is to put the Test2 action on another controller which is not decorated with this attribute.
Back in MVC 3 it appears it was indeed not possible to do (as mentioned Darin Dimitrov), but if anyone using MVC 4 (and up) comes across this question, he\she should be able to use AllowAnonymous filter to achieve the result. So the code would become:
[Authorize]
public class TestController : Controller
{
public ViewResult Test()
{
return View();
}
[AllowAnonymous]
public ViewResult Test2()
{
return View();
}
}

Switch off request validation in the view

is it possible to switch request validation in the view.
I would like to switch it off in the view because of this bit of code in the base controller
protected override void Execute(System.Web.Routing.RequestContext requestContext)
{
if (!this.CurrentStore.IsDefault)
{
IStoreRepository storeRepo = ObjectFactory.GetInstance<IStoreRepository>();
IStoreEntity store = storeRepo.GetById(this.CurrentStore.Id);
this.CurrentStore = store;
}
base.Execute(requestContext);
}
it fails in base.Execute(requestContext);
N.B I do not wish to switch it off for my entire site. I would like to switch it off in a few action methods.
In MVC you don't do it at the view level, you do it at the controller or a method of the controller level. You can use ValidateInput attribute for that, for example:
public class HomeController : Controller
{
[ValidateInput(false)] // prevent validation on this method
public ActionResult Index()
{
return View();
}
}

Catching and resolving AmbiguousMatchException

I would like to catch the AmbiguousMatchException whenever it is thrown and then write some code to resolve it. For example, I have an action ChangePassword which should be called only if the user is logged in. I have another method RenewPassword which must be called if the user is not logged in. I have given the same action name to both these methods.
[HttpPost]
[ActionName("ChangePassword")]
public ActionResult RenewPassword(ChangePasswordModel model)
{
...
}
[Authorize]
[HttpPost]
[ActionName("ChangePassword")]
public ActionResult ChangePassword(ChangePasswordModel model)
{
...
}
I want to use the same action name because I do not want the view to have to worry about which action to call. I know that I can write a custom FilterAttribute which will do the reverse of what AuthorizeAttribute does, apply it to the RenewPassword method, and thereby resolve the ambiguity. However, this seems like too much work for a very simple need.
Any better ideas? Is there a built in way to say that a particular action should be executed only for anonymous users and not for logged in users?
If you don't views having to worry about which action to call why not writing a reusable HTML helper:
public static class HtmlExtensions
{
public static MvcForm BeginChangePasswordForm(this HtmlHelper htmlHelper)
{
if (htmlHelper.ViewContext.HttpContext.User.Identity.IsAuthenticated)
{
return htmlHelper.BeginForm("ChangePassword", "SomeController");
}
return htmlHelper.BeginForm("RenewPassword", "SomeController");
}
}
and inside your view:
#using (Html.BeginChangePasswordForm())
{
...
}
and in the corresponding controller:
[HttpPost]
public ActionResult RenewPassword(ChangePasswordModel model)
{
...
}
[Authorize]
[HttpPost]
public ActionResult ChangePassword(ChangePasswordModel model)
{
...
}

Resources