{.NET + SQL_Server + Azure + devLeadership + technology}

Menu

Category Archives: Architecture

When I saw a new item in my RSS feed from Rob Conery about MV* I was immediately interested to read it, because I have been working on trying to create my web app pages using MVP, but am unable to find any examples beyond the most basic.

I would love to see how other people manage the interactions between the Controller and the View, to see how it compares to how I am doing it.

My view interfaces tend to be kinda large. For example, if I have a button that I hide and show depending on business rules, I will create a MyButtonVisibility property on the interface can set the properties from the controller.

I would be interested to see how others deal with things like the hiding / showing of items. I could see wrapping more of that kind of functionality in the view, and giving the view some more logic but I think you would then start to lose some of the testability.

Anyway, the articl on Rob’s blog was really to talk about creating an MVC style architecture for subsonic itself, not the pages that use it. However, Rob seemed to suggest that the new changes would aid you in using MV* in your pages by forcing you into good habits.

But I really don’t understand how that would work. If you have code that does:

MyGridView.DataSource=Product.FetchAll();
MyGridView.DataBind();

And you change it so that you use a Controller (or Manager as I have called it when loading Business Objects or DTOs) to look like this:

I had previously read and heard in presentations by Rocky Lhotka that performance comparisons between Web Services and Remoting showed that they were basically the same, and that when talking about RPC protocols ES killed them both so badly (order of magnitude) that it wasn’t worth fretting over the small diff between WS and remoting.

Much to my suprise the giant performance improvement when using ES was only seen when calling empty functions. In otherwords, it was basically a test of the transport. Some “real world” tests showed ES performing faster than most other methods, but sometimes something like Remoting TCP Binary would outperform it as well.

In the tests that actually did something, the performance across the board was usually fairly comperable. I guess this makes sense. If you liken the round trip of an RPC call to a person going on a business trip, the speed of the airplane is less important that the time it takes the person to do the job at the end of the trip. So even if your plane takes 3 hours instead of 2 hours, if your going to be staying for a week then that 1 hour isn’t a big deal.

The major conclusion is to not pass datasets. Datasets are serialized as XML even if you are using the binary serializer. I have posted some stuff on this topic as well on my blog so you can search for it if you want.

Sub ReflectionSearch(ByVal strPattern As String) Dim a As Reflection.Assembly Dim m As Reflection.Module Dim t As Type Dim al As New ArrayList Dim sl As New SortedList Dim strAssemblyName As String

For Each strAssemblyName In DefaultAssemblyList() a = Reflection.Assembly.Load(strAssemblyName) For Each m In a.GetModules For Each t In m.GetTypes al.Add(t) Dim strFullName As String = t.FullName If Regex.IsMatch(strFullName, strPattern, RegexOptions.IgnoreCase) Then sl.Add(strFullName, Nothing) End If Next Next
Next

Dim de As DictionaryEntry For Each de In sl Console.WriteLine(de.Key) Next Console.WriteLine(sl.Count.ToString & " matches for " & strPattern) End Sub

Used to determine which device filter is in place, and use this information to decide how to display the page.

AddParsedSubObject

Always

All

Notifies the server control that an element, either XML or HTML, was parsed, and adds the element to the server control’s ControlCollection object.

DeterminePostBackMode

Always

Page

Returns a NameValueCollection object that contains the data posted back to the page. The presence of the page hidden fields VIEWSTATE and EVENTTARGET is used to help determine whether a postback event has occurred. The IsPostBack property is set when the DeterminePostBackMode method is called.

OnPreInit

Always

Page

Called at the beginning of the page initialization stage. After the OnPreInit method is called, personalization information is loaded and the page theme, if any, is initialized. This is also the preferred stage to dynamically define a PageTheme or MasterPage for the Page.

OnInit

Always

All

Performs the initialization and setup steps required to create a Page instance. In this stage of the page’s life cycle, declared server controls on the page are initialized to their default state; however, the view state of each control is not yet populated. A control on the page cannot access other server controls on the page during the Page_Init phase, regardless of whether the other controls are child or parent controls. Other server controls are not guaranteed to be created and ready for access.

OnInitComplete

Always

Page

Called after page initialization is complete. In this stage of the page’s life cycle, all declared controls on the page are initialized, but the page’s view state is not yet populated. You can access server controls, but they will not yet contain information returned from the user.

LoadPageStateFromPersistenceMedium

Postback

Page

Uses the Load method of the System.Web.UI.PageStatePersister object referenced by the PageStatePersister property to load any saved view-state information for the Page object.

LoadControlState

Postback

All

Restores control-state information from a previous page request that was saved by the SaveControlState method.

LoadViewState

Postback

All

Restores view-state information from a previous page request that was saved by the SaveViewState method.

OnPreLoad

Always

Page

Called after all postback data returned from the user is loaded. At this stage in the page’s life cycle, view-state information and postback data for declared controls and controls created during the initialization stage are loaded into the page’s controls. Controls created in the OnPreLoad method will also be loaded with view-state and postback data.

OnLoad

Always

All

Notifies the server control that it should perform actions common to each HTTP request for the page it is associated with, such as setting up a database query. At this stage in the page lifecycle, server controls in the hierarchy are created and initialized, view state is restored, and form controls reflect client-side data.

RaisePostBackEvent

Postback

All

Notifies the server control that caused the postback that it should handle an incoming postback event.

OnLoadComplete

Always

Page

At this point in the page life cycle, all postback data and view-state data is loaded into controls on the page.

OnPreRender

Always

All

Notifies the server control to perform any necessary prerendering steps prior to saving view state and rendering content.

OnPreRenderComplete

Always

Page

At this stage of the page life cycle, all controls are created and the page is ready to render the output. This is the last event called before the page’s view state is saved.

SaveControlState

Always

All

Saves any server control state changes that have occurred since the time the page was posted back to the server. If there is no state associated with the control, this method returns a null reference. Custom controls using control state must call the RegisterRequiresControlState method on the Page before saving control state.

SaveViewState

Always

All

Saves any server control view-state changes that have occurred since the time the page was posted back to the server. If there is no view state associated with the control, this method returns a null reference.

SavePageStateToPersistenceMedium

Always

Page

Saves any view-state and control-state information for the page. The SavePageStateToPersistenceMedium method uses the Save method of the System.Web.UI.PageStatePersister object referenced by the PageStatePersister property to store view-state and control-state information for the page.

Render

Always

All

Initializes the HtmlTextWriter object and calls on the child controls of the Page to render. The Render method is responsible for creating the text and markup that is sent to the client browser. The default Render method calls RenderChildren to write the text and markup for the controls contained on the page.

OnUnload

Always

All

Used to do target-specific processing in the Unload stage of the control lifecycle. Typically, these are cleanup functions that precede disposition of the control.

CSLA as well as well as the proxy architecture I created for my last project, utilize serialization of objects to be passed across the wire, and deserialized on the other side into the same type of object.

This is different from passing datasets, which are then read into business objects. We are actually passing the serialized version of the business object.

So what happens if you make a change to a business object such as adding a public property. Will clients who have the old version of the Business Object be forced to upgrade?

To see the answers along with some sample code for testing this out click on the link to read the full article.

So lets say you have a class that exposes 20 properties and 40 methods. This business object is deployed on hundreds of clients computers. When they send the BizObject over the wire, it is deserialized back into the exact same object on the server.

But now, for whatever reason, you need to add 1 property to this BizObject. For the current set of clients using this business object, you don’t really need to deploy the updated change unless you have to in order to keep it from breaking.

So do you need to redeploy? Probably not.

I serialzied a business object into a base64 encoded string and then added a public property to the object and tried to deserialize it with the “old” serialized string. The result? It worked. The properties that had values when I first serialized it kept their values. The fact that there were new properties didn’t cause a problem.

How about going the other way: removing a public property that had a value when it was serialized, but doesn’t exist with deserialized. Again, this works.

When doesn’t it work? When you are trying to deserialze into a different class, or a different namespace for the same class.

So you can’t serialize classA and deserialize it into classB, even if both expose the exact same signature. The same goes for namespaces. If you serialize classA, and then change it’s namespace and try to deserialize it, you will get an exception.

I had a chance to ask Rocky a couple of questions that had been bugging me about CSLA.

1) He agreed that using the method of multiple result sets in datareader is not really a good idea in some instances, where a dataset would be much more useful.

2) He suggested that you should usually not have an object that is sometimes a child and sometimes a parent. I am not sure I agree with idea. I believe I understand his point that if you are dealing with a Project object that has a collection of Employees assigned to it, you probably don’t need the Employees to be as complex as if you were dealing with an Employee who is assigned to a bunch of Projects, but at the same time you are talking about writing 2 classes with 2 sets of data access scripts, vs 4 classes and 4 sets of data access. But, he said that there are techniques for making a business object be both a parent and a child. This is apparently detailed in Ch 7.

3) He mentioned that people have built UI Frameworks that run on top of CSLA. I will have to look into this.

4) He was showing an example using an ASP.NET MultiView control, looked like a great way to enable multiple views of the same data.

5) I didn’t get a chance to ask him about serialization and deserialization of classes that have small differences. For example if you serialze an object and use the same byte array to deserialize a similar class, will it blow up if small changes are made, like you add a public property? I will have to try this out myself.

In all, Rocky was a very good speaker. Very engaging, funny, and on point.

Oh and I won the raffle at the end, to get a copy of his book, the one I just paid 60 bucks for :-).