ASP.Net MVC: Create a link method… ie JUST GIVE ME THE STUPID URL

One thing that kind of annoys me is the situation where you just want a url, but you don’t want one of the prepackaged links using:

   Html.RouteLink
Or
   Html.ActionLink

Mostly because you want to be able to create your own html and you only want the created url. Well turns out there’s a method for this: The RouteUrl method on the UrlHelper class. Down side is that it’s not static and takes a few lines to use, so not cool UI design side. Well here’s a method that uses that method and gives you a method to exact a method of victory. I think that sentence had promise, but fell short of complete failure.

Anyways, here it is… The “Just give me the stupid url” method, CreateUrl for short.

        public static String CreateUrl
        (
          RequestContext context,
          RouteCollection routeCollection,
          String routeName,
          String controller,
          String action,
          RouteValueDictionary routeValues
        )
        {
            //Create the helper
            UrlHelper neededHelper = new UrlHelper(context, routeCollection);

            //get the route to check what it is holding at far
            //as defaults go
            var neededRoute = (Route)routeCollection[routeName];

            //this might be overkill honestly.  Basically in case the
            //Route contains the "controller" key only then add it to the
            //values for the route.  Otherwise just ignore.  It's possible
            //someone might pass in a controller/action but the route
            //doesn't take them. At which point you'll
            //be showing the "Aw maaaaan" face.

            if (!String.IsNullOrEmpty(controller) && neededRoute.Defaults.ContainsKey("controller"))
            {
                routeValues.Add("controller", controller);
            }

            if (!String.IsNullOrEmpty(action) && neededRoute.Defaults.ContainsKey("action"))
            {
                routeValues.Add("action", action);
            }

            //And then the call to create the url string.
            return neededHelper.RouteUrl(routeName, routeValues);
        }

And in use View side:

  <a href="
  <%
  CreateUrl
  (
    Html.ViewContext.RequestContext,
    Html.RouteCollection,
    GeneralConstants.RouteDefault,
    "SomeController",
    "SomeAction",
    new RouteValueDictionary { { "id", 1 } }
  )
  %>"
  >
  Something is linked
  </a>

Now mind you I did use a link there so it seems like a silly example. However, you can do many other things now that you just have the url itself.

Dynamic Markup Property Collection for a WebControl

I wasn’t exactly sure how to write this title as it’s not easy to explain in a short sentence, however I can say that I am completely embarrassed by the result and may have to consider hiring a title consultant. However, for now it will have to do.

Ok so what is this about? Well let’s say you have the control from the last example and you don’t want a list of controls in the markup, but maybe you want a list of strings set in the markup. (Say for a list of settings) Or even better, let’s say you have controls already on the page but you want our ParentControl (Yes I said “our” but no I’m not proposing… yet) to do something with those controls. Say we want to have the ParentControl to assign some javascript to certain buttons on the page. Ok yeah, kind of dumb but that’s the example I made. I supposed you could think of it like this: You want a validation control to validate multiple controls but you want to give it the names of the controls in the markup. Anyways, let’s stick with the example I already have.

First off you’ll need to create a new class, something that you want to hold the information in. (Although truth be told I could do something way easier and just use a list of strings, but this should prove more interesting) Here’s the one I have:

  namespace Test.Frontend.ControlInControl
  {
    public class ChildControlDefinition
    {
        public String ControlName { get; set; }
    }
  }

Pretty sweet? Eh? Eh? No? Ok. So now we have a class, and that’s like wow. Now with the same attributes from the old example, build the WebControl:

    [ParseChildren(true)]
    [PersistChildren(false)]
    public partial class ParentControl : UserControl
    {
        public List<ChildControlDefinition> NamedControls { get; set; }
    }

Holy smokes, that just got way complicated compared to the last example. I added a whole new property NamedControls that is a list of the ChildControlDefinition class we created. Now you might notice that the AddedControls property from the old example isn’t there anymore. I just removed it to simplify this one.

And then there’s the markup:

    <asp:Button ID="mainButton" runat="server" />
    <uc1:ParentControl ID="ParentControl1" runat="server" >
        <NamedControls>
            <examples:ChildControlDefinition ControlName="mainButton" />
        </NamedControls>
    </uc1:ParentControl>

Now you might notice two things here:

1) There is a mark up section named “NamedControls” just like the collection. Can you guess why?

2) examples:ChildControlDefinition : This is the class type name and the TagPrefix for where the class is. For this to work, you have to register the assembly the class is in EVEN IF the class is in the web application assembly. So it would look like this:

<%@ Register Assembly="Test.Frontend" Namespace="Test.Frontend.ControlInControl" TagPrefix="examples" %>

Now what does this do for anyone? Possibly it prevents you from dying a little inside but it also allows you to find those controls within the usercontrol… Ah buh? Don’t worry, I’ll show you!

    [ParseChildren(true)]
    [PersistChildren(false)]
    public partial class ParentControl : UserControl
    {
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            NamedControls.ForEach(ConnectButtonToClick);
        }

        private void ConnectButtonToClick(ChildControlDefinition control)
        {
            Button foundControl;

            foundControl = Page.FindControl(control.ControlName) as Button;

            if (foundControl != null)
            {
                foundControl.OnClientClick = "alert('clicked'); return false;";
            }
        }

        public List<ChildControlDefinition> NamedControls { get; set; }
    }

See what I did there? SOMETHING COMPLETELY USELESS and yes you too can now have that power. However, there might be something worth taking home from that example. From the list of ChildControlDefinition I was able to get the control name that I wanted to attach the worthless alert script to and attach it. How was that done? Well I just iterated through the ChildControlDefinition list, used the Page.FindControl method to find the control, and then set the OnClientClick method.

Now this example is pretty stupid but I hope you can see the overall value of this. One would be a paging controller that has a list of paging control names that it iterated through and sets various events so they can all work in harmony like one great big continuation of the Hands Across America utopia that just didn’t seem to make it.

Now to spin it Nintendo User Manual Style:

Think you are bad enough for Dynamic Controls? Take grab of the power within and dare to conquer! Take a chance, the world can be your for the taking! Dynamic is waiting…

Add Controls to Control in ASP.Net (With Less Pulp)

So this should be a fairly easy showing and you’ll be on your way quickly. Hell most likely you won’t finish this sentence before going somewhere else. BUT for those who brave this post, you will be rewarded… I hope.

So here’s the problem, you have a UserControl/WebControl/ExtenderControl/ScriptControl/… (Seriously?) that you want to be able to add controls to in the markup like thus:

<SomeControl>
  <ControlList>
    <asp:Label />
    <asp:Label />
  </ControlList>
</SomeControl>

As you see here, the idea is that SomeControl actually can dynamically house controls based on the markup. Seems like this should be hard, but in reality it’s pretty simple. First start with creating a user control, which I hope you know how to do. (I’m calling it ParentControl) Second open up the class file and let’s add some stuff.

    [ParseChildren(true)]
    [PersistChildren(false)]
    public partial class ParentControl : UserControl
    {
        public ParentControl()
        {
            addedControls = new List<WebControl>();
        }

        private List<WebControl> addedControls;

        public List<WebControl> AddedControls
        {
            get
            {
                return addedControls;
            }
        }
    }

And honestly, that’s the code needed but I’ll give a literary once over to make sure things are clear.

So first off you have to add a list of controls to the eh… control and create a property that is used to access it and this can actually be done verbosely:

        //Field
        private List<WebControl> addedControls;

        //Instantiation on constructor
        public ParentControl()
        {
            addedControls = new List<WebControl>();
        }

        //Property to access
        public List<WebControl> AddedControls
        {
            get
            {
                return addedControls;
            }
        }

OR the easy way (Which is not what the original example showed:

        public List<WebControl>AddedControls { get; set; }

As you can see, the 2.0 auto property syntax will actually work for this. So if you like that, you can save yourself some typing.

Ok so now we have a property, and field if you choose, to handle this. Sounds way too easy right? Well the magic is in the attributes:

    [ParseChildren(true)]
    [PersistChildren(false)]
    public partial class ParentControl : UserControl

And you’re all set. Now the markup:

    <userControl:ParentControl ID="ParentControl1" runat="server" >
        <AddedControls>
            <asp:Label ID="labelHi" runat="server" />
        </AddedControls>
    </userControl:ParentControl>

Still waiting for this to get complicated? Well you’re going to waiting for a long time because that’s it. When page load comes around will now have a list with the label in it. Pretty nice huh?