Archive for the ‘MVC’ Category

(using MVC4 beta)

In some cases it is not easy to alter the header values to negotiate the content type returned from WEBAPI.

There is a QueryStringMapper object you can add to the Media Type Formatter objects that allow you to use a query string to negotiate the content format.

In the example below,  I am adding a query string parameter ‘format’ to the mapping. When ‘format’ == ‘xml’, the content type is ‘text/xml’ and the XmlMediaTypeFormatter is used.

I run this in the ‘Application_Start’ method of the Global.asax 

            foreach (var item in GlobalConfiguration.Configuration.Formatters)
            {
                if (typeof(XmlMediaTypeFormatter) == item.GetType())
                {
                    item.AddQueryStringMapping("format", "xml", "text/xml");
                }
            }

Example api call – http://localhost/api/foo?format=xml

Advertisements

I’m using the first Umbraco 5 (Jupiter) RTM on a new project.

One of the requirements of this project is to aggregate RSS feeds, so I built a simple plugin leveraging the System.Xml.Linq objects.

To make the plugin, I created a new MVC 3 project in visual studio to build and test the functionality.
I would have added the Umbraco test site to my solution and setup post build commands to copy the files from my project to Umbraco folders, but for some reason I was not able to run the Umbraco site from Visual Studio. I think its a system problem though.

I’ve also used the HTML Agility pack to parse the feed descriptions and remove bad markup.

Here is the  code to grab the RSS Feed and parse it with the HTMLAgilityPack –


    public static class Reader
    {
         public static IEnumerable GetRssFeed(string feedUrl, bool trimDescription = true)
         {
             XDocument feedXml = XDocument.Load(feedUrl);
             XNamespace dc = "http://purl.org/dc/elements/1.1/";
             string exp = @"^.{1,500}";
             if (trimDescription == false)
                 exp = ".*";
             var feeds = from feed in feedXml.Descendants("item")
                         select new Rss
                         {
                             Title = feed.Element("title").Value,
                             Link = feed.Element("link").Value,
                             Description = Regex.Match(ParsedDoc(feed.Element("description").Value).DocumentNode.InnerText, exp).Value,
                             PubDate = feed.Element("pubDate").Value,
                             Creator = feed.Element(dc + "creator").Value
                         };
             return feeds;
         }

         public static HtmlAgilityPack.HtmlDocument ParsedDoc(string source)
         {
             HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
             doc.OptionWriteEmptyNodes = true;
             doc.OptionFixNestedTags = true;
             doc.LoadHtml(source);
             return doc;
         }


    }

 

And the RSS class…

 


    public class Rss : IComparable
    {
        public string Link { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public DateTime PubDateDate { get; set; }
        public string Creator { get; set; }


        public string PubDate 
        {
            get
            {
                return _pubDate;
            }
            set
            {
                _pubDate = value;
                DateTime pubDateDate = DateTime.MinValue;
                DateTime.TryParse(value, out pubDateDate);
                PubDateDate = pubDateDate;
            }
        }
        private string _pubDate;

        // Implement the default CompareTo method with the PubDate
        // as the parameter. 
        //
        public int CompareTo(Rss other)
        {
            // If other is not a valid object reference, this instance is greater.
            if (other == null) return 1;
            return PubDateDate.CompareTo(other.PubDateDate);
        }


    }

In Umbraco, I created a folder in the plugins directory following the Dev Dataset examples.
I placed the HTMLAgilityPack DLL and XML, and my DLL in this folder to allow the CSHTML to call the classes.

I created 2 new document types in Umbraco for an ‘RSS List’ and ‘RSS Feed Item’. On the RSS List template, I grab all the children of that node (which are of type ‘RSS Feed Item’) and grab the properties from them using the DynamicModel.

In the Umbraco RSS List template…


@inherits Umbraco.Cms.Web.RenderViewPage

@functions {
    //Add public properties here to create Macro Parameters

    protected List<Zeroth.Umbraco.RSSReader.Rss> aggregatedFeed = new List<Zeroth.Umbraco.RSSReader.Rss>();
}

@{
    foreach (var child in DynamicModel.Children)
    {
        aggregatedFeed.AddRange(Zeroth.Umbraco.RSSReader.Reader.GetRssFeed(child.url, true));
    }
    aggregatedFeed.Sort();
    aggregatedFeed.Reverse();
}

<h2>@DynamicModel.CurrentPage.Name</h2>

<div class="rssList">
@foreach (var child in aggregatedFeed)
{
    <div class="rssItem">
        <div class="rssLink">
            <a href="@child.Link" target="_blank">@Html.Encode(child.Title)</a>
        </div>
        <div class="rssByLine">
            <span class="rssPubDate">@child.PubDate.Replace("+0000", "")</span><span> | </span><span class="rssCreator">@child.Creator</span>
        </div>
        <div class="rssDescription">
            @( new HtmlString(child.Description) )
        </div>
    </div>
}
</div>

One of the great MVC3 benefits is how easy it is to create helpers to inject HTML into your views.

After reading this post, I decided I would use Bart Czernicki’s example to create an MVC3 helper ‘cshtml razor engine style’.

You can place the following code in your App_Code folder (in a cshtml file).
I use a file called ‘Helpers’ and place multiple helpers in the same file. You could also create multiple files there to namespace your helpers if you have a bunch.

 @helper SilverLightHostControl(
            string silverlightXapFileLocation, // URI Location of the Silverlight XAP file
            string minimumRuntimeVersion = "4.0.50826.0",
            string objectContainerWidth = "100%",
            string objectContainerHeight = "100%",
            string onErrorJavaScriptFunctionName = "onSilverlightError",
            string divObjectTagId = "silverlightControlHost",
            string iFrameStyle = "visibility:hidden;height:0px;width:0px;border:0px"
            ){
    <div id="@divObjectTagId">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="@objectContainerWidth" height="@objectContainerHeight">
            <param name="source" value="@silverlightXapFileLocation"/>
            <param name="minRuntimeVersion" value="@minimumRuntimeVersion" />
            <param name="onError" value="@onErrorJavaScriptFunctionName" />
            <param name="background" value="white" />
            <param name="autoUpgrade" value="true" />
            <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
            <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
            </a>
        </object>
     </div>
} 

To use the helper in your view, call it like this –
@Helpers.SilverLightHostControl(“/ClientBin/SilverlightSurface.xap”)

For help integrating a Silverlight project in MVC, check this post out –
http://www.iwantmymvc.com/using-silverlight-with-mvc-and-json

FYI – This still works for MVC4.

I am using the Razor view engine for this example; in Visual Studio 2010 with MVC 3 web application template. For more explanation, check out Scott Guthrie‘s blog here or here or one of the other many great posts he has written.

I like to use the SiteMap control for an easy horizontal navigation menu at the top of the content area and styled like a tab interface. Adding a few thin borders and the right background colors can create a great tab effect.

The new Razor view engine makes it very easy to create dynamic templates.

  • Create a SiteMap in the root directory of your web application and add some nodes
  • Create an App_Code folder in your solution if you do not have one already
  • Add a new blank partial view file called Helpers.cshtml in the App_Code folder
  • Enter the following into the file –

(more…)