ASP.NET 2.0 hasn’t put the final nail in the coffin of Frames. It does however provide some better alternatives depending on what you are trying to achieve.
I googled up some comparisons of Frames, Master Pages and the ICallBackEventHandler a good overview article on ASP.net 2.0 sates in favour of master pages:
• “Bookmark a page and recall all the information on the specific page, not just the default frame page. A master page isn't really a frame. It's a single page that contains collated content from the master page and the content page that builds on the master. Therefore it looks and acts like a single Web page rather than a frame.
• Work by means of controls and tags rather than HTML. Thanks to Visual Studio, you don't have to worry about opening and closing frame tags or modifying countless HTML attributes to ensure that each frame displays in the correct fashion. You can simply create the place holder and modify its properties through Visual Studio.
• Leverage Visual Studio's code creation to visually design the layout, manage the frames, and provide all of the plumbing to link the content pages into the master page. You can add new content without having to worry that the overall HTML layout of the page will be affected. “
Migrating from ASP.NET 1.x to ASP.NET 2.0
By Jayesh Patel, Bryan Acker, Robert McGovern - Infusion Development, July 2004
https://www.mainfunction.com/DotNetInAction/Technologies/display.aspx?ID=2760&TypeID=17#master
And this extract from an interview with Scott Guthrie Microsoft’s ASP.net Architect discusses how the new callback manager (ICallBackEventHandler) which is basically a XMLHTTP wrapper can also help in reducing the amount of visible page refreshes.
“…So, one is to do what we call, out-of-bound call backs, where you can stay on the same page as an end user, but then through script, you can actually make a call back to the server and fetch new data that you populate down to the client, without having to, again, refresh the entire page, without having to lose scroll position, etc.
…
So will out-of-bound callbacks spell the end of the evil IFRAME?
The IFRAME today has a bum wrap in terms of reputation. I think the combination of out-of-bound callbacks as well as some of the things we're doing in terms of master pages, to provide much cleaner layout of a page, where you can go ahead and rather than have to rely on frames in order to cleanly separate, or integrate content into a site, you can now rely on master pages. I think the combination of those two are going to put the hurt on the IFRAME out there. It's still fully supported, but the nice thing is, there's much richer mechanisms you can rely on now. “
http://www.theserverside.net/talks/videos/ScottGuthrie/interview.tss?bandwidth=56k
Well master pages seem a fantastic tool for development. They give you page inheritance, reusability you can even nest them giving the developer a simple way for you to ensure consistent look and feel to an entire application. So from a developer’s point of view they rock.
But what about the user experience well even if a content page “inherits” a master page each time the page is requested the entire page will refresh whether it is the content part or the master part of the page. Users hate full page refreshes, developers hate trips to the server to retrieve redundant html, the menu bar and advertisement is already on the client’s browser so why go and get it again (even if it is cached on the server).
Can implementing the ICallBackEventHandler help, well yes and no. Use of this technique can only refresh data. For example, enable the user to page through a grid without refreshing the entire page. You can’t really use this to redisplay the entire content area of the page if it contains asp: web controls (well I have done it but using Frames would be much much easier).
If you haven’t already come across the concept of XML Data Islands it has been around for a while along with Frames and XMLHTTP (now the ICallBackEventHandler). This technique requires the use of the DHTML XML tag you use this to build a client side repository of data in XML. For example if a user is entering data to complete a form over a number of pages, it would be more beneficial if you stored the data on the client between pages until the user reaches the final page and presses submit and only then hit the server to update your data source. This potentially has no effect on the dreaded page refresh it is great for relieving the pressure on your database server however. Note this is not the only use for XML Data Island the example is a common one however.
So the only way to stop the entire page refreshing if you are using asp: or user controls on your page (these need to be rendered by the asp.net runtime) and only refreshing the content area of a page is still through the use of Frames. Unfortunately in ASP.net Beta 2 unlike ASP.net 1.X it doesn’t ship with a Frameset template although there will be an online template available and adding the tags yourself won’t cause injury.
So what are the best practices I have come up with many seasoned web developers will already practice these however for those beginners and intermediates I hope this will be of some help and relive you of trial and error driven development. Some of you may disagree with these and I would like to hear back from you guys. Remember it is the users we are building these web applications for not the developers.
Use master pages when
• Not concerned about a full page refresh
• Development requires a highly modifiable inheritable page standard and users will live with a page refresh
• Need to be allow the user to bookmark a specific page
Use the ICallBackEventHandler when
• Want to refresh data or images in a control and not refresh the entire page
• Want to refresh part of the page with simple HTML (no asp: controls) and not refresh the entire page
Use XML Data Islands
• You want to build stores of data on a client and by doing this reduce the number of hits to update the servers data source
Use Frames when
• Don’t want full page refreshes
• Have complex asp: control driven pages which can’t be refreshed by data only i.e. the asp: controls need to be generated into html by the web server first
• Need multiple areas of the page to be refreshed at different times by the user
R. Addis & A. Rambabu
An instance of the Biztalk MessageContext is created and stays with each message until the message leaves Biztalk. It contains properties such as RecievePortName, RecieveFileName, MessageType i.e. all the meta data for a message.
If you want to modify this meta data you need to modify the IBaseMessageContext using either the following methods, this may be done in either a custom pipeline component or inside an orchestration:
IBaseMessageContext.Promote: Make the Message Context property a promoted property
IBaseMessageContext.Write: Make the Message Context Property a distinguished property
Where you make the call to modify the message context depends on WHEN it should be modified. If you want to use a message context property to correlate two messages you should do it inside a custom pipeline component. If you want to set the message context during processing after some decision logic do so in a Message Assignment shape in an Orchestration. We are only looking at doing it in a custom pipeline component.
An example of using this would be if you had two input files which needed to be correlated in an orchestration based on an id or date in the filename which defined a relationship between those files. Another example of a problem this would solve is found here: http://www.eggheadcafe.com/ng/microsoft.public.biztalk.server/post21008841.asp
So in both these cases we want to look at the file name of the message, extract and promote part of it so we can either use that extracted information to either correlate two or more incoming messages or base some decision logic on those properties. The way I’m going to show you how to do it is to actually overwrite the RecieveFileName property with the extracted value from it.
Notes:
• I am going to show you how we did it instead of just giving you code or a solution.
• Although I think “Biztalk Server 2004 Unleashed” tries too cover too much in one book it does have a very good explanation of Pipelines and what the different stages of a pipeline should implement.
1) Download Martijn Hoogendoorns’ Pipeline Component Wizard http://www.gotdotnet.com/Workspaces/Workspace.aspx?id=1d4f7d6b-7d27-4f05-a8ee-48cfcd5abf4a and install it:
a. Unzip the source code, open the Visual Studio sln file and rebuild the PipelineComponentWizardSetup project.
b. Right-click the PipelineComponentWizardSetup project and select “Install” to install it.
2) In your Biztalk project add a new project and select Biztalk Server Pipeline Component Project set the following properties in the wizard.
3) Explaining all of the Interfaces which are implemented in a pipeline component is not in the scope of this post. I will however advise you to take a quick look and familiarise your self with the following methods which implement the PropertyBag: Load, Save, ReadPropertyBag, WritePropertyBag.
The method of the Decode Pipeline Component which does the Biz is the Execute method to which we add the following code:
public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(Microsoft.BizTalk.Component.Interop.IPipelineContext pc, Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg)
{
//Make sure the message contexts property name isn't empty
if (_PropertyName != null)
{
//Get the current value of the property
object oPropertyValue = inmsg.Context.Read(_PropertyName, _PropertyNamespace);
if (oPropertyValue != null)
{
string sPropertyValue = (string)oPropertyValue;
System.Text.RegularExpressions.Regex oReplaceRegularExpression =
new
System.Text.RegularExpressions.Regex(_ReplaceRegularExpression);
//Replace the regular expression with the value specified
sPropertyValue =
oReplaceRegularExpression.Replace(sPropertyValue,_Value);
//Either promote or distinguish the property
if (_PromoteOrDistinguish == "Promote")
{
inmsg.Context.Promote(_PropertyName, _PropertyNamespace,
sPropertyValue);
}
else if (_PromoteOrDistinguish == "Distinguish")
{
inmsg.Context.Write(_PropertyName, _PropertyNamespace,
sPropertyValue);
}
}
return inmsg;
}
Note I have also changed the Value property to allow you replace with an empty string so you can remove characters using a regular expression.
public string Value
{
get
{
return _Value;
}
set
{
if (value == null)
{
_Value = string.Empty;
}
else
{
_Value = value;
}
}
}
4) Well that’s the development easy aye thanks to the Pipeline Component Wizard. As for testing I guess you could do this by STOP PRESS a much better way of debugging a pipeline:
• referencing the new pipeline component project in your Biztalk project
• change the output path in the pipeline components project properties dialog to C:\Program Files\Microsoft BizTalk Server 2004\Pipeline Components
• adding the compiled pipeline dll as a component by right clicking on the pipeline component toolbar and choosing add new item then selecting the Biztalk Pipeline Components Tab
• placing a breakpoint in the Execute method code
• add the component to the decode stage of a pipeline where you want to use it set the properties on the decode component to (this is just a suggestion, the regular expression tries to remove all the characters around a date which was in a filename setting the ReceivedFileName property to a date)
• deploy your Biztalk project
• set up a receive port & location
• attach to the BTSNTSvc,exe process
• drop a file in the receive location and hopefully the debug runtime will stop at your breakpoint
5) To use the modified and promoted RecieveFileName property to correlate two messages
• create a Correlation Type and set the “Correlation Type Properties” property to FILE.ReceivedFileName
• create a Correlation Set based on this type
• initialise the correlation set property of the receive shape (for the messages which need to be correlated) to the name of the correlation set you created above
R. Addis