Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • David Conlisk 432 posts 1008 karma points
    Nov 13, 2013 @ 13:26
    David Conlisk
    0

    Helper method in cshtml dealing with dynamicnull

    Hi all,

    I'm using Umbraco v6.1.6 (Assembly version: 1.0.5021.24867) MVC.

    I have a datatype which represents a bunch of 1-6 columns, each column has title (textstring), content (richtext) and link (ucomponents url picker). The easiest way for the editor (I think) is to have a tab on the documenttype for each column - I'd love to use Repeatable Custom Content, but it doesn't render very nicely.

    So, I have attributes title1, title2, ..., title6, content1 - content6, etc. in my doc type. So in my .cshtml partial view, I'd like to have a helper function like this:

    @helper RenderColumn(string title, System.Web.HtmlString content, DynamicXml link, string classname) 
        {
            if (!string.IsNullOrEmpty(title)) 
            {
            <div class="@classname">
                <h2>@title</h2>
                @content 
                @if (link != null && link.RawXmlElement != null) 
                {
                    var urlPicker = UrlPickerState.Deserialize(link.RawXmlElement.ToString());
                <p>
                    @if (urlPicker.NodeId.HasValue && urlPicker.NodeId.Value > 0)
                    { 
                        <a class="btn btn-primary btn-lg" role="button" href="@umbraco.library.NiceUrl(urlPicker.NodeId.Value)">@urlPicker.Title</a> 
                    }
                    else
                    { @urlPicker.Title }
                </p>
                    }
            </div>
            } 
        }
    

    And I could call this like so:

    @RenderColumn(CurrentPage.title2, CurrentPage.content2, CurrentPage.link2, classname);
    

    However, I run into all sorts of problems. If title2 is not set, for example, then CurrentPage.title2 is of type DynamicNull rather than an empty string, so I get an exception because RenderColumn "has some invalid arguments".

    I know it's not ideal to have six sets of properties like this, but if anyone can suggest a better way I'm all ears! I don't want to use MNTP with a folder of shared column nodes because it's too complex for users - I want a single node to represent a row of columns of content on the page.

    Thanks!

    David

  • Michael Law 7 posts 37 karma points
    Nov 13, 2013 @ 23:05
    Michael Law
    1

    Hey Dave,

    I always find working with the Dynamics a bit hard to manage, especially parsing values that return as DynamicXml!

    I find casting the values to expected types works best for me to handle nulls, so using the approach below to silently fail the cast:

    var title1 = CurrentPage.title1 as string;
    

    Or doing some sort of Type comparison just to be sure it is what your ecpecting e.g.

    var content = (CurrentPage.content1 is IHtmlString ? CurrentPage.content1 : new HtmlString(string.Empty);
    

    Then i'd use those on your method as you are guaranteed the correct types. Im not sure if the above code will compile alright, never tested it, just and idea =)

    It is a drawback of this MVC approach where loads of logic is unnecessarily in the view and would defo be better served on a controller or service class. Or you could maybe create a whole whack of HtmlExtensions to parse the dynamic values on a CurrentPage to the types you wold expect to follow the old DRY principles.

    No idea on a good solution for the doc type layout though bar using nodes and pickers, would be interested to hear how others would approach that.

    Cheers

  • David Conlisk 432 posts 1008 karma points
    Nov 14, 2013 @ 11:15
    David Conlisk
    0

    Hi Michael,

    Thanks for the response. I'd ended up going down the road of your second suggestion with the type comparisons, but as you say, I'm ending up with lots of logic just to call the helper method - which I was hoping to avoid.

    I'll look into the HtmlExtensions idea though...

    Cheers,

    David

  • David Conlisk 432 posts 1008 karma points
    Nov 14, 2013 @ 12:57
    David Conlisk
    0

    OK for anyone else who is interested, here is a solution that works. It's not the most elegant, certainly not as elegant as I'd hoped, so if anyone can help improve on it then I'm all ears.

    Firstly, you can't create an extension method that takes a dynamic parameter: http://stackoverflow.com/questions/15391115/what-causes-extension-methods-cannot-be-dynamically-dispatched-here

    So I have to call the methods directly. Here is an example of one that, given an Umbraco property as a parameter, safely returns a HtmlString regardless of whether or not that property actually exists on the Umbraco node (which returns the problematic DynamicNull object):

        public static HtmlString GetRichText(dynamic item)
        {
            if (item is DynamicNull) return new HtmlString(string.Empty);
            if (item is IHtmlString) return item;
            return new HtmlString(string.Empty);
        }
    

    If the property is not of the correct type then an empty string is returned (in this case). I've compiled this into a class library, and have set up an alias in the using statement in my .cshtml razor template:

    @using myHelper = MyClass.Helpers.UmbracoHelperExtensions
    

    So now I can safely call my original Helper method like this:

    @RenderColumn(myHelper.GetTextString(CurrentBlock.title1), myHelper.GetRichText(CurrentBlock.content1), myHelper.GetUrlPicker(CurrentBlock.link1), classname)
    

    which is a bit better than having loads of logic in my view.

Please Sign in or register to post replies

Write your reply to:

Draft