Register before entering the main site - asp.net

When someone visits my site and if there isn't any admin registered they should be redirected to that Adminregistration page.
Now this should ONLY happen when there isn't any admin registered whatsoever. So it should only happen when the database is fresh and empty without data.
I know I can put a check with a validationattribute on all controllers. But I find that a bit of a hack and well... The check should be completely removed when there is 1 registered anyway.
So is there another way to accomplish this?

If you have a base controller that all your controllers inherit from, you could put the "validationattribute" you mention on the base controller to trigger the validation on every request, if that is what you want.
Edit
You could store a global variable in web.config called say AdminIsRegistered that is set to false when the application is first shipped. Then you change that value programatically when the first admin registers like this and set it to true. Your custom attribute set on the base controller could then simply check that value on every request, as long as it is set to false, the attribute redirect the user to the registration action, otherwise it does nothing.

The best way to do this is with a global filter. You register it once in your application, and every action that executes will hit the filter first. All you have to do is add it to the global filter collection on Application_Start:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalFilters.Filters.Add(new AdminRequiredAttribute());
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}

Related

How to get custom user property in Razor ASP.NET without any ViewModels?

I created my new custom property for User in ASP.NET project ("DarkTheme").
I have a problem (see below). I can access User.Identity.Name without any ViewModels. I can access User.Identity.IsInRole() and so on. But I cannot access my new property ("DarkTheme"). I do not want to use viewmodels (I would have to rewrite the whole application). Is there a way to go to the place where ASP.NET makes User.Identity.Name accessible without any ViewModels and add "DarkTheme" property?
I didn't find the answer to this problem, but I have a workaround.
I used User.IsInRole("DarkTheme") attribute to pass the value to the view (and load different css files depending on the value). It is the only role that user can assign to himself without manager permission.
You could use OnActionExecuted method in your controller in combination with dynamic ViewBag
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (Request.IsAjaxRequest() || filterContext.IsChildAction) return; // you don't need styling for ajax requests which return json
base.OnActionExecuted(filterContext);
YourUser user = ... // get user from db/claims or get theme from cookies etc.;
ViewBag.DarkTheme = user.DarkTheme;
}
and in view it will be invoked simply by #ViewBag.DarkTheme, no namespace needed

Detect what Attributes are set on a controllers action during Application_AuthenticateRequest

I get a call to Application_AuthenticateRequest which I use to perform some authentication logic. Something similar to:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
if (System.Web.HttpContext.Current.Request.IsAuthenticated)
{
....
}
}
That works generally fine, however in some cases my controller actions have the AllowAnonymous attribute attached, and I do not want the code to execute. The is no problem if the user is not logged in, however, if the user is logged in and they attempt to access one of these views, I run into an issue.
What I'm wondering is, if there is a way I can detect what attributes are set on my action in the Application_AuthenticateRequest call. Or if I could even detect if the current page requres authentication?
So far I haven't been able to figure this out, but it seems like it should be fairly simple. I'm wondering if someone could point out something that I'm missing?
This question is little old. But I came across to find an answer. I found a solution by using System.Web.HttpContext.Current.SkipAuthorization
This returns true if the action has [AllowAnonymous] attribute,
Else this returns false if the action has [Authorize] attribute.

Using Tempdata in a class

I made an annotation for pages that require logging in, if the user is not logged in it will be redirected to the login page. I would also like to add an error which requires tempdata to view the error. Otherwise i have to set an message and check if the user is logged in every controller.
So my question is if it's possible to set a tempdata in a non controller, if it's possible how could i achieve this?
Do you mean you made a action filter for those pages? If so, you can access tempdata in the filter context.
public void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Controller.TempData
...
}

ASP.NET MVC 3 - How to restrict areas in an efficient way?

I've got an ASP.NET MVC 3 site with an admin panel (don't we all? :) - I've used my own solution for a very secured login system.
Now, on each view in the admin controller I need to make checks that the user is logged and has the proper authorization, so each time I run the same verification and authorization methods on each view separately.
How could I make the same checks for all the requests to a certain controller? (I mean, right all the checks only once and in one place)
(I also would like to have an exception, so I could allow user to use the login page inside the admin controller and outside of it)
Thanks!
Use an attribute on the controller. Either the standard AuthorizeAttribute (see this) or write your own.
What you're looking for is action filter attributes. They are basically an attribute you can place on a controller that allows you to intercept calls to every action method within a controller and are therefore perfect for security as you can deny/accept requests: http://msdn.microsoft.com/en-us/library/system.web.mvc.actionfilterattribute.aspx
If you want to limit the entire controller instead of the individual actions you could place the [Authorize] attribute like so:
[Authorize]
public class PageController : Controller
{ ... }

Asp.Net call function from a different *.aspx.cs page

If I have a button inside one page for example "main.aspx". And upon being clicked I want the clicked method in "main.aspx.cs" to call a function from a different *.aspx.cs page but also redirect to that *.aspx page...is that possible?
A more concrete example of what you're trying to do would be useful. Otherwise you'll get all sorts of answers, many of which will be off the mark.
You should put common code in the App_Code folder. You should also not have any business logic inside a forms code-behind.
The fact that you need one page to call a method in another page indicates that you haven't done this. Pages are for displaying and interpreting actions, but they should not hold any of the business logic.
e.g. a lame example of a shopping cart.
ProductView.aspx - calls Cart.AddToCart(Product p)
CartView.aspx - displays all items in the cart, and the user
can update or remove items.
- calls Cart.RemoveItem(int cartIndex)
- calls Cart.UpdateItem(int cartIndex, int newItemCount)
Cart itself doesn't belong in either CartView.aspx or ProductView.aspx. It instead belongs in ~/App_Code/Cart.cs
So your solution could look something like
/ (root of your web folder)
Product/
ProductView.aspx
ProductView.aspx.cs
Cart/
CartView.aspx
CartView.aspx.cs
App_Code/
Cart.cs
Product.cs
Also, to add the App_Code folder if it's not already there, right-click the web project and select Add ASP.NET folder and choose App_Code
You need to understand the ASP.NET Page lifecycle and you'll see why this is not Kosher. If you really need to call a method from multiple pages, it sounds like a good candidate for some external class/object.
Alternately, instead of using a querystring parameter, you can set a Session flag and then redirect to this new page. Then clear the session flag when you call that page's method.
In a very basic way, for Main.aspx to go to Other.aspx and to pass some small amount of data on the querystring to indicate an action.
Main.aspx
protected void OnSomeButtonClicked(object sender, EventArgs e)
{
if( someCondition )
{
Response.Redirect("~/Other.aspx?action=runAway");
}
}
in Other.aspx
protected void Page_Load(object sender, EventArgs e)
{
if( !IsPostBack )
{
if( "runAway".Equals(Request.QueryString["action"] )
{
RunAway();
}
}
}
You should also read up on Server.Transfer versus Response.Redirect. Which one to use is situation dependent.
Also note that QueryString parameters can be altered easily by the user, so always verify them and never trust the user.
Why don't you just redirect with a querystring parameter and then execute the function on the destination page?
Instantiate an object from your other page class and call the method.
protected Button1_Clicked(Sender s, Eventargs e){
MyNamespace.Page_Other po = new MyNamespace.Page_Other();
po.Method1();
Response.Redirect("~/page_other.aspx");
}

Resources