Scope of a Static Variable in Seam - seam

If I define a static variable in a class having Page Scope, then what will be the Scope of the Static Variable? Will it persist the data even if I navigate away from that page and then come back to that page(here by page I mean the xhtml page on which I am referring to the static variable)?

Static fields are associated with the class, rather than with any object. Seam Scopes don't change the meaning of static. The page context allows you to associate state with a particular instance, but if you assign a value to a static field that value will be share by all instances regardless of your Seam Scope.
Will it persist the data even if I navigate away from that page and
then come back to that page(here by page I mean the xhtml page on
which I am referring to the static variable)?
Yes, since you have one classloader for your web application, the scope of your static variable should be more than page scope.

Related

Is it possible to have classic asp.net dynamically load subtypes of declared webcontrols

I want to be able to declaratively specify the webcontrols of any given page in the standard way, but have the runtime not necessarily new up instances of the types I specified, but rather for instance check against web.config whether a different webcontrol (which would inherit from the specified one) should be used instead.
for instance I could have a webcontrol in the path /templates/controls/default/PersonSelector.ascx and another one in the path /templates/controls/CUSTOMER_A/PersonSelector.ascx (inheriting from the first)
so if my config indicated that I preferred to load controls from the CUSTOMER_A folder where available, and since it would be available in this case, the actual markup which was used for the page would come from .../CUSTOMER_A/PersonSelector.ascx. All code which compile-time assumed that it was in fact an instance of ../default/PersonSelector.ascx would still work since it is actually a subclass.
This would afaik be a major benefit to our site which is a multitenant site in which 99.5% of the generated html is identical across all our customers (except for skinning, naturally) but some of the customers wants different headers/footers/selection-logic etc. So far all the differences are handled by bloating the controls and if/else-ing all over the place.
I realize that asp.net is probably not the weapon of choice for doing this kind of thing, but it's the one we've got, and the codebase is large enough that a rewrite would be a pain.
Yes, you can load user controls dynamically using the LoadControl method. Provided that you have Control1 and a Control2, where Control2 inherits from Control1, you could do this in a page:
//Obtain control name in the format "~/pathFromApplicationRoot/ControlName.ascx"
string controlName = MethodThatDecidesTheControlNameToLoad();
//Load control
var userControl = (Control1)this.LoadControl(controlName);
//Add it to page
AControlSuchAsAPlaceHolder.Controls.Add(userControl);
Edit:
In order to be able to specify your user controls declaratively in markup I guess you could make the user control replace its own content with the tenant specific control if the config told it to override.

Best way to generate url via Page.GetRouteUrl in a helper class?

I have just added routing in a new asp.net 4 web forms application, and have got my route table set up ok and page requests are working fine.
What I now want to do is use the Page.GetRouteUrl method whenever I need to generate one of my seo friendly Url's. I started to implement this across various pages then thought it might cut down on code a bit if I had a method in one of my own helper classes, that constructs this url (using the Page.GetRouteUrl method) as I might have several parameters that need to be specified against the Page.GetRouteUrl method each time.
However, within my helper class, it doesn't know what 'Page' is. I was thinking I could pass in 'Page' from the page that wants a routed url to be generated, but in some cases I want to construct one of these Url's in another class which doesn't know what 'Page' is, and in that scenario wouldn't be able to pass it in as a param (and therefore wouldn't be able to use the Page.GetRouteUrl within my helper class).
What is the normal approach when wanting to use Page.GetRouteUrl within classes that don't have an instance of the Page object?
You can pass Page as a constructor parameter, or this is actually the page reference:
var page = HttpContext.Current.Handler as Page;
You can cast it to the page type. Depending on the type of requests you are making, it may not always be page (say from a web service call, etc.).
HTH.

Best way to set master page properties in content page in asp.net?

There are different ways to set the title for content pages from Master page
by findcontrol
by creating property in master page and setting the value in content page
As both method requires an object creation of master page which will be little heavy
myMasterPage myMaster = (myMasterPage)this.Master;
so I have tried it by creating a class and it worked -
public class clsmaster
{
public static clsmaster objmaster = new clsmaster();
public strtitle {get;set;}
}
Now I just need to access this static object and set the property in the content page and in the master page I just need the controls to take the value from this class (clsmaster).
I would like to know which one is the better approach and why with description please?
I generally advise creating a BasePage class of some sort that encapsulates the behavior you want through all of your pages, these objects are assumed to always have the same master page, if you need other setups then you can create other objects as necessary.
From there you can create some properties or methods to allow the BasePage objects to access the master page or its associated properties in a very easy to code way such as this.Title = "MyTitle"
You can get fancier and create some virtual methods on your BasePage class that you can then override on the physical pages as necessary, to set titles, etc, as needed, without ever grabbing the Master page object directly (which yes, is annoying and ugly). This might look something like this.Title = GetTitle(); (GetTitle is a virtual method on the BasePage that is overridden in the child pages as needed for those pages you want to set a title for).
This makes strong use of inheritance and lets you add functionality to all of your pages very easily, it may be overkill for what your doing but I've never found a situation that was too simplistic for this architecture, it just works really well. I personally find this design far better than constantly using FindControl(), which tends to be error-prone when control ID's change, etc.
FindControl() is bad because if the control ID's change, then you might forget to update them in the FindControl reference, and now it'll break the next time its executed, I stay well away from static stuff like this if at all possible for this very reason, it's a cheap, quick but error-prone solution.
Accessing the Master page directly isn't inherently bad, I just can't stand stuff like:
myMasterPage myMaster = (myMasterPage)this.Master
Gets old, is uglier than it needs to be, wrap it in an accessor property at the very least ;)
I like the following better:
Title = "My Title"; // Property
or
Title = GetTitle(); // Virtual method

Is it possible for a custom asp.net control to load types at design time from the assembly hosting the control?

I have a custom server control for asp.net. One of the properties available to it is a generic object. That generic object has custom attributes that are read and used to customize the rendering of the control.
At run time, this is no problem, since all I need to do is find all the attributes on the instance that gets passed into the control.
However, just as the "DataSource" member of controls can call up a list of object types at design time, I would like to be able to bring up a list of types in the host assembly. There is no need for actual instances, since I'm rendering based on attributes.
This is an example property from the host control:
[Browsable(true)]
[TypeConverter(typeof(TheObjectConverter))]
public object TheObject
{
get { return _theObject; }
set { SetTheObject(value); }
}
What I want to have happen is to have TheObjectConverter be able to load the assembly of the host page for the control.
None of the following seem to work
.GetReferencedAssemblies();
.GetExecutingAssembly();
.GetCallingAssembly();
.GetEntryAssembly();
.GetAssembly();
I even a full recursion against .GetReferencedAssemblies(), with no luck. It seems I am unable to load the assembly of the control's host at design time. Is that correct, or is there a way to do this?

Using a Base Controller for obtaining Common ViewData

I am working on an ASP.NET MVC application that contains a header and menu on each page. The menu and header are dynamic. In other words, the menu items and header information are determined at runtime.
My initial thought is to build a base Controller from which all other controllers derive. In the base controller, I will obtain the menu and header data and insert the required information into the ViewData. Finally, I will use a ViewUserControl to display the header and menu through a master page template.
So, I'm trying to determine the best practice for building such functionality. Also, if this is the recommended approach, which method should I override (I'm guessing Execute) when obtaining the data for insertion into the ViewData.
I'm sure this is a common scenario, so any advice/best-practices would be appreciated! Thanks in advance!
EDIT:
I did find the following resources after posting this (of course), but any additional anecdotes would be awesome!
http://www.singingeels.com/Blogs/Nullable/2008/08/14/How_to_Handle_Side_Content_in_ASPNET_MVC.aspx
How do you use usercontrols in asp.net mvc that display an "island" of data?
Depends on where your information is coming from. We have standard view data that we use to generate some of the information we have on screen that we create in just this fashion. It works well and is easily maintained. We override the View method to implement strongly typed view names and use this information to retrieve some of the data that the master page requires as well.
You could write a helper extension to render the header/menu
That way you could have it show in different places in the view should you need to, but only one place for maintenance.
public static HtmlString MainMenu(this HtmlHelper helper)
Use a base controller class to implement generell filter methods. The controller class implements some filter interfaces IActionFilter, IAuthorizationFilter, IExceptionFilter and IResultFilter which are usefull to implement some common behavior for all controllers.
If the menu data is the same on all pages but different for each unique user.
Generate the menudata in an OnAuthorization or Initialize method of your controller base class. First will be called on authorization. Initialize will be called before every action method. You have access to ViewData Context. Generate the menudata there.
Put the view content for menu and header into the master page and access generated ViewData there.
I tackled a similar design challenge a couple months ago - implementing a breadcrumb feature that changes as user navigates from page to page.
I overrided the OnActionExecuting method to gather the breadcrumbs and store them in ViewData (I use the name of the action as the breadCrumb of the view). Then I updated the Master page to include a user control that takes the ViewData and renders the breadcrumbs.
One thing to be aware is that if you were using the default ASP.NET MVC error handling attribute [HandleError] and your error page is using the same Master page that attempts to read the ViewData, you will soon find out that you can't access ViewData from your error page and it will raise an exception. Depending on whether you need the ViewData for failure scenarios, the viable solution is to use a separate Master page or do this: How do I pass ViewData to a HandleError View?
I'll answer your question with another question. Will the base controller have to determine what type it really is in order to generate the proper menu data? If so, then you're defeating the purpose of polymorphism and the code to generate the data should go in each controller, perhaps in OnActionExecuting if the menu is the same for all actions. Pushing it back down into a parent class seems likely to end up with some switch statement in the parent class doing what each derived controller really ought to take care of.

Resources