in

ASP.NET Weblogs

Andy Smith's Blog

Page.RegisterStartupScript('Andy', 'MetaBuilders_WebControls_GainKnowledge();');

October 2003 - Posts

  • Usefullness of Cross Page Posting

    Paul has voiced his concerns about the limits of asp.net v2 cross page posting.

    I too had the same reaction when I saw what it does and what it doesn't do. The reason that I changed my mind about it, and now I like the way it's done, is that I thought about the problem it sovled, and the problem we think it was supposed to solve.

    I'll start off with the problem that we thought it was supposed to solve. Web forms that post to other applications are really doing a kind of web service hack. You send some name/value pairs as parameters to an open port over http, and it returns the result as generally-non-parsable html, to be interpreted by the human sitting at the client browser. It's also kind of analogous to having a button in your windows forms application that opens a new application with some given parameters, maybe using some kind of Process.Start thing. To me, this kind of cross application interaction seems very outdated, and we should be using web services instead. For those of us forced to interact with these systems, I'll present my ideas for how to deal with it in a minute.

    Now onto the problem it is intended to solve. Many people making web apps these days are old hands at windows application development. In these environments, when you open a new form, you can still access the objects in the opener form, and use them as parameters and such. This is the development model that Cross Page Posting is designed to support. No more weird things like posting back to the same page, putting items in the Context.Items, and Transfering to the “real”  page. You just go to the real page from your button and access the previous page's objects as naturally as you would in a windows application. I think it's great that the asp.net team made this not only possible, but also incredibly easy and intuitive.

    So ya, now back to the problem of interfacing with outside applications. I've been giving this some back-burner thought for a while now, and I've come to the same conclusion that the asp.net team has. You don't want to directly post to outside sites from pages that are part of your asp.net web application. Especially not with serverside controls forming the name/value pairs being sent. The base issue, it seems to me, is that the asp.net framework, in exchange for providing you with a server control model, has somewhat taken over the clientside names of the html elements, as well as added a few unseen name/value pairs.

    So, maybe what we want is a component that exists for the purpose of being a middleman between our applications controls, and the name/values that the external site is looking for. Maybe this component has a TargetUrl property, and a NameValueCollection which we populate it with the exact names we want, and the server controls provide the values. We then call DoYourThing() on the component, and it does all the neccessary goop to move the user to the url we want.

    That hand waving “goop” might do something like this...

    If the target is expecting a GET request, we can simply do a Response.Redirect after building the querystring from the NameValueCollection. However, if it needs a POST, which most do, it's gets a bit more complicated. We can have a custom IHttpHandler that generates a regular old form element, with hidden inputs containing the name/value pairs we want. Our component makes a Transfer or Redirect to that handler, with an appropriate querystring built from the NameValueCollection. The handler emits the proper “transitional” form to the client browser, with some script to automatticly submit the form as soon as it is received. Of course, have a submit button for non-script-enabled clients.

    I dunno, maybe my solution is a great idea, maybe it's not... but I do think that Cross Page Posting is a great idea and implementation, and that Cross Site Posting with the html generated by Pages and ServerControls is a bad idea.

  • favoriate asp.net v2 features #3, Web Resources

    This one is fairly well covered in Nikhil's Server Control Presentation, but I thought I'd mention it too. With Whidbey you can easily add images, script, etc to your server control quite easily. Gone are the days of requiring some “client files” folder on the server, because you can just embed your stuff into the assembly as resources, and use the built in WebResource IHttpHandler to get them out. Many people ( including me ) have been including custom handlers in their server controls to do this, but now I don't have to rely on web.config entries for the control to work. It Just Works. And not only do you get runtime availability of the resources, but the handler also works at design time! Awesome.
  • Favorite Whidbey Features #2, Single Instance Templates

    Templates are great at providing a way to specify the UI for a databound control. The control takes care of the behavior, and the template, designed by the page developer, takes care of the UI. However, not everybody wants to use templates with databinding. Some people want to provide controls that offer behavior tied to a specific template, only instanciated once. It's handy to use Templates to allow the page developer to specify the look of a view, but there's a small problem having to do with codegen.

    You see, people are used to dragging controls onto a form, and being able to use the ID of that control as a variable tied to that control. This is some “magic” that the asp.net aspx compiler does that creates a member on the Page that is tied to the object instance declared in the tag. However, in V1.x, controls inside templates weren't created as members on the page, presumably because it was assumed that template controls would be part of a repeating pattern such as in a repeater. This assumption is not always true, as in the case of wanting a template to be used only once, to provide the UI for you control's behavior.

    So now v2 offers a TemplateInstanceAttribute with an associated TemplateInstance enum, with Single and Multiple values. So now, if your control does not implement INamingContainer and you have a Template property with the TemplateInstance.Single attribute applied, any controls declared inside your template, it is now available as a Page level member.

    Neat, eh?

  • In No Particular Order, Favorite New Feature #1, ControlState

    By now, every good control developer knows that you implement a public property using ViewState. Heck I have a macro for adding viewstate-backed properties, that turns:

    String Foo ““

    into

    public virtual String Foo {
      get {
        Object savedState = ViewState[“Foo“];
        if ( savedState != null ) {
          return (String)savedState;
        }
        return ““;
      }
      set {
        ViewState[“Foo“] = value;
      }
    }

    The viewstate is a great mechanism for storing your control properties, but it has a flaw/disadvantage. Consider what the EnableViewState property does, and how it affects controls. When EnableViewState is set to false, there's no difference between a property that doesn't matter too much, such as BackColor, and properties that are vital to the workings of the control, such as a CurrentPanel property, which might control which panel is shown on a multi-panel control. Without storing which panel is currently shown, there's no way to raise a mythical CurrentPanelChanged event, because the one being sent in the form post has to be compared with the previous, and you won't have the previous value because ViewState is disabled.

    So now enters ControlState. This is another “hidden input based round trip state keeper” like ViewState. However, it is meant for storing these vital properties, so that your control is still functional when viewstate is disabled. So while BackColor, FontSize, and their friends can still be stored in the unreliable ViewState, Really Important© properties can go in ControlState, so the control can do the basic things that it says it does, regardless of other factors.

    It's not quite as easy to use as viewstate, as there's no StateBag to throw things into. You have to override LoadControlState and SaveControlState, as well as notify the page that you need ControlState, with the obligatory Page.RegisterMeForDoingSomethingOutOfTheOrdinary method.

    But easy or not, it's useful and puts more power in the hands of control developers, and that's all it takes to make my List Of Control-Developery Happiness©.

    I thought I might mention the one downside to this new mechanism. The problem is going to be in deciding on what is important enough to go into ControlState, and what isn't. I can imagine these battles between page developers trying to keep their bandwidth down ( which is the intention of EnableViewState=false), and control developers trying to ensure their controls do what the docs say they do. But overall, I think it's good to have the choice.

  • building whidbey controls

    Now that the cat is out of the bag, I'll be writing a few entries on my favorite new asp.net whidbey features that are targeted at control development. Most of the my favorites are design time related, but there's a few runtime enhancements that make some control behaviors possible that just weren't before.
  • Flagged Enum Properties

    Flagged Enums present a problem in asp.net as custom control properties because the asp.net page parser/compiler doesn't know how to generate pages where those properties have been set in the declarative tag. It causes a null reference exception to be thrown. I did a little thinking about it, and came up with a fairly workable solution to it using a public string property to wrap the flagged enum. So I wrote up a little article describing the technique. As usual, if you can come up with a better solution, please, let me know.
  • custom webcontrols and serverside events

    I got “instructed” by a friend to blog some of my more informative forum/list/newsgroup posts, especially the following one which describes the general mechanisms of events with webcontrols, so here you have it. (Names and emails removed to protected the guilty)

    Here is an abbreviated look at the lifecycle:

    Init
    Load ViewState Data
    Load PostBack Data
    Load
    Fire Events
    PreRender
    Render

    To fire control events at a base level, you implement either
    IPostBackDataHandler or IPostBackEventHandler.

    When you implement IPostBackEventHandler, you are saying that when the
    page has determined that your control was the cause of the post back it
    will call your RaisePostBackEventHandler implementation during the "Fire
    Events" phase. Buttons implement this, for when they are clicked. In
    that method you should raise your event.

    When you implement IPostBackDataHandler, you are saying that your
    control has post data that you need to examine in order to determine if
    an event needs to be fired. The page will call your LoadPostData
    implementation during the "Load PostBack Data" phase. Here you look at
    the post data to determine if you need to raise an event, but you don't
    raise it now. If you return true from this, the page will call your
    RaisePostDataChangedEvent implementation during the "Fire Events" phase.
    Now you raise your event. Textboxes implement this interface, to
    determine if they should raise their TextChanged event.


    Those are the low-level event mechanisms. However, if you are
    implementing a composite control, you have another, higher-level choice,
    which is to handle the events raised by your child controls in order to
    raise your own events. Sometimes this is done via event bubbling, other
    times by creating a whole new event. To do this, progmaticly hook up the
    eventhandler as you are creating the child controls. This is the way the
    datagrid works.


    __
    Andy Smith
    Chief Code Monkey

    > -----Original Message-----
    > Sent: Tuesday, September 23, 2003 1:50 PM
    > Subject: [aspnet-controlbuilding] a custom control with events
    >
    >
    >
    > If I want to create a control with events, sort of how the
    > datagrid has
    > onitemdeleted, updated etc.
    >
    > Where would these events fire in a control I build?  WOuld it
    > be in the
    > PreRender()?  I have to create events and then allow those
    > events to be able
    > to added to by the developer?
    >
    > I realize some events will fire under cirtain circumstances
    > (prob. most),
    > but generally where are global events fired?  PreRender?
    >
    > E.G  MyControl.OnSomethingHappend += MyControlHandler(MyMethod);
    >
    > ?

  • Exceptions Suck Less

    I'm gonna have to agree with Dare in completely disagreeing with Joel. Exceptions do The Right Thing by default. Error results do the The Wrong Thing by default. That's the base difference, and it's an important one. I'm glad I don't have to work on any code inherited from “return code” people.
  • a little facelift

    As cool as the msdn css was, I decided to brand my blog with my own site's look. So I sat down for about 15 minutes and now, those of you not using aggregators should see a metabuilders style. Hope you like it.
  • It took me 25 years to know what I want

    Lately, I've been thinking alot about my future. Thinking about what kind of development I want to do...

    Looking back over my time as a code monkey, I've always been happy, got in the zone, and lost total track of time, when I was developing tools, creating web infrastructure, and targeting the developer. Not when I was writing Yet Another CRUD Application or targeting the end user. The problem with that, of course, is that there is obviously a larger market for end user apps than developer server tools and components. However, I think I've proven I have the kind of programming chops required for this line of development. And not only that, but I have an enthusiasm for this stuff that's hard to find. I like making web tools so much that I've been writing and giving them away on metabuilders.com since .net was in beta.

    So ya... I've decided that this is going to be my goal. I've had lots of advice from friends in the dev community that I should just start up my own business on metabuilders.com, but really, I just don't like the business side of it. I want to code. So I guess what my plan is... is to find a component development company that wants to pay me to do what I love. So i'll be talking to people, looking for this kind of opportunity, but if you are, or know somebody who is, in a position to hire for something like this, please let me know.

More Posts Next page »