Chris Risner . Com

No Parameterless Constructor when Binding to a Custom View Model

Posted on: 2/14/2011 2:46:00 AM by

In the process of rewriting this blog’s framework, I ran across an issue with binding my MVC views to custom view models.  Specifically, when I tried updating my model on post back like so:
   1:  [AcceptVerbs(HttpVerbs.Post)]
   2:  public ActionResult Contact()
   3:  {
   4:      ContactScreen screen = new ContactScreen();
   5:      TryUpdateModel(screen);

Or when I tried to get the view model object directly in as a parameter for the method like so:
   1:  [AcceptVerbs(HttpVerbs.Post)]
   2:  public ActionResult Contact(ContactScreen screen)
   3:  {

I was consistently getting this error:
No parameterless constructor defined for this object.
Unfortunately the stack trace didn’t really give me much information.  What it did tell me was that the issue was coming from the DefaultModelBinder.  After commenting out different properties of my ContactScreen object (the view model my view was bound to) I discovered that the culprit was this right here:
public SelectList AuthorSelectList { get; set; }
Basically, the default data binder in MVC 2.0 doesn’t understand how to instantiate a select list when you’re not passing data over.  Since my SelectList is normally instantiated in a method that loads different data to the screen, I only ran into the error when it was trying to do the data binding behind the scenes.  Fortunately, there is a way around this that doesn’t involve us having to alter the default binder.  We can tell the class to exclude certain elements when it’s binding.  This is done very easily by putting a Bind attribute on the class and telling it to exclude our property like so:
   1:  [Bind(Exclude="AuthorSelectList")]
   2:  public class ContactScreen : ScreenBase
   3:  {
   4:       public SelectList AuthorSelectList { get; set; }
 
Unfortunately, we do have to handle custom binding of the value selected for the select list, but we only have to do it for our one value instead of everything in our class.
Categories: .Net, MVC, Programming
Bookmark and Share
First Article

Veritas–Continuing the UI–Part 12

Posted on: 2/13/2011 8:23:45 PM by

Continuing from where we left off last time, we’re going to continue trying to focus on the UI for our site.  The first thing we’ll do is create a user control for our top menu.  We’ll put the basic navigation for our site up there and we’ll load it all from the BlogMenuItem table.  In our UserControls folder (in our Views) we’re going to add a new View User Control named UcTopBar.  The markup for this control is pretty simple:

   1:  <div id="topBarMenu" align="center">
   2:      <ul id="topMenu">
   3:          <% foreach (BlogMenuItem item in Model.blogMenuItems)
   4:             { %>
   5:             <li>
   6:                  <%= (item.IsView ?
   7:                     VeritasForm.ActionLink(item.LinkText, item.ViewName, "Home")
   8:                     :
   9:                      VeritasForm.ActionLink(item.LinkText, "ViewContent/"+item.ViewName, "Home"))
  10:                   %>
  11:             </li>
  12:          <% } %>
  13:      </ul>
  14:      <b id="topMenuBottom" style="padding-left:0px"></b>
  15:  </div>
The only really important thing here is the unordered list topMenu.  Within that we’re iterating over the BlogMenuItems.  For each one it’s either a View or a link to something we’ll display using the ViewContent page.  That’s it.  The topMenuBottom bold tag is just used as a line to underline the menu.  That’s it for our navigation menu.  In order to show this View User Control we’ll add this to the master page right under contentcolumn:
<% Html.RenderPartial("~/Views/UserControls/UcTopBar.ascx"); %>
Next, we’ll do the same thing on the side and create a Side Bar View User Control.  Before we get into what this control will look like, we need to figure out what we’re going to put on it.  We’re certainly going to want to put Syndication information so we’ll add a link to our RSS feed.  We’ll also want to have the ability to link to Twitter and Facebook and maybe some others.  We’ll want to show a list of all the categories that our entries fall into.  Lastly, we’ll want to show ads.  We might add more later but this is a good start for now.  One interesting thing to note for the RSS feed is that we want the ability to display our feed through where we’re going to host it and also through Feedburner (if we’re going to use that). 
   1:  <div class="syndication">    
   2:      <%--Blog Entry Feed--%>
   3:      <%= string.IsNullOrEmpty(Model.blogConfig.FeedburnerName) ?
   4:          "<a href=\"" + VeritasForm.Content("~/Syndication/rss.aspx") + "\"><img src=\"" 
   5:              + VeritasForm.Content("~/Content/Media/feed.png") 
   6:              +"\" alt=\"Site Feed\" style=\"border-width:0px;\" /> RSS (blog)</a>"
   7:          :
   8:          "<a href=\"http://feeds.feedburner.com/"+ Model.blogConfig.FeedburnerName + "\"><img src=\"" +
   9:              VeritasForm.Content("~/Content/Media/feed.png") +"\" alt=\"Site Feed\" style=\"border-width:0px;\" /> RSS</a>"        
  10:      %>
  11:      <%--Blog Feedback Feed--%>
  12:      <% if (Model.blogConfig.EnableFeedbackRssFeed)
  13:          { %>                
  14:          <br /><a href="<%= VeritasForm.Content("~/Syndication/commentRss.aspx") %>">
  15:                  <img src="<%= VeritasForm.Content("~/Content/Media/feed.png") %>"
  16:                   alt="RSS Feed" style="border-width:0px;" /> RSS (comment)</a>        
  17:      <% } %> 
  18:      <%--Social Networks--%>
  19:      <% if (!string.IsNullOrEmpty(Model.blogConfig.FacebookUrl))
  20:         { %>
  21:         <a href='<%= Model.blogConfig.FacebookUrl %>'><img src=
  22:                                      "../../Content/Media/facebook_logo.png" /></a>
  23:         <br />
  24:      <% } %>
  25:      <% if (!string.IsNullOrEmpty(Model.blogConfig.TwitterUrl))
  26:         { %>
  27:         <a href='<%= Model.blogConfig.TwitterUrl %>'><img src=
  28:                                        "../../Content/Media/twitter_logo.png" /></a>
  29:         <br />
  30:      <% } %>
  31:  </div>
  32:  <%-- Tags --%>
  33:  <div class="sideBarTags">
  34:      <% Html.RenderPartial("~/Views/UserControls/UcTagCloud.ascx"); %>            
  35:  </div>
  36:  <%--Side bar ads--%>
  37:  <div class="sideBarAds">
  38:      <% if (Model.blogConfig.BlogMarketingInfo.ShowSideBarAds) { %>
  39:          <%= Model.blogConfig.BlogMarketingInfo.AdScriptSideBar %>
  40:      <% } %>
  41:  </div>

Nothing surprising here.  In the RSS feed part, we’re checking to see if we should show the blog’s rss feed directly or use feedburner.  Then we’re checking to see if we want to show a link to the feedback (comment) rss feed.  All of this links to pages we haven’t actually created yet but eventually will.  Then we’re choosing whether or not to show the facebook and twitter links based off of the blog config.  Then we’re showing a new user control called the Tag Cloud.  Lastly, we’re checking to see if we should show an ad script specific to the side bar.  The last piece we’ll cover today is the tag cloud.  The tag cloud is primarily just a list of the categories we’ve associated with our entries.  However, we want each categories text to be proportional to how many entries are associated with it.  So for example, if I have ten entries associated with “.Net” and one entry associated with “MVC” then ".Net” will be in bigger text.  We’re going to accomplish this by putting specific classes on our html links depending on the association counts. 
   1:  <div align="center">
   2:      <span id="categoriesHeader">Categories</span>
   3:      <div id="tags">
   4:        <%
   5:          foreach (var categoryTag in Model.blogCategoryTags)
   6:          {%>        
   7:              <%= "<a href=\"" + VeritasForm.Content("~/Category/" + categoryTag.CategoryTitle) 
   8:                  + "\" title=\"" + categoryTag.CategoryTitle + "\" class=\"" 
   9:                  + VeritasForm.GetTagClass(categoryTag.CategoryUseCount, categoryTag.TotalArticles) 
  10:                  + "\">" + categoryTag.CategoryTitle + "</a>"%>
  11:          &nbsp;
  12:          <% }%>
  13:      </div>
  14:  </div>

Again, nothing special.  Each link is being built and makes use of the GetTagClass method within the VeritasForm object.  This method will return something like “tag1” or “tag4” dependent upon the popularity of the category.  These class names will then map to our CSS file where we will change the text size from lower (for “tag1”) to higher (for > 1).
 
In addition to everything we did above, we’re also going to set up our About page and the Contact page.  I won’t go over this in detail here as it’s all pretty straight forward and should (if you’ve been keeping up so far) be very easy to read and understand.  As always, you can download the latest Veritas code to review yourself.

Categories: .Net, MVC, Programming, Veritas, Web
Bookmark and Share
First Article

Veritas–Continuing the UI–Part 11

Posted on: 2/8/2011 4:31:00 AM by

The first thing we do as we continue working on our UI is clean up a few things from the last time.  While we created screen objects so we could tightly bind our views to something, we didn’t do the same for the Master pages.  Since we didn’t do that, we ended up casting our BlogConfig object on the master page like so:

   1:  <script type="text/javascript" src='https://www.google.com/jsapi?key=
   2:  <%: (ViewData["BlogConfig"] as BlogConfig).GoogleApiKey %>'></script>

Specifically we’re talking about line 2.  We really want to avoid this wherever possible.  However, since this is the Master Page, we’re not currently binding it to a specific object type (besides our VeritasViewMasterPage).  We can get past this by binding it to the ScreenBase object.  Since we’re passing screen objects which all descend from ScreenBase to our views as the model, this will work and it means that on our master page, we can access any public properties or methods of the ScreenBase class.  So in our master pages (all of them, not just Site.Master), we’ll change our inherits line to:

Inherits="Veritas.UI.Web.Views.VeritasViewMasterPage<Veritas.BusinessLayer.Screens.ScreenBase>"
Now, we’ll just add a BlogConfig variable to our ScreenBase class:
   1:  public BlogConfig blogConfig
   2:  {
   3:      get { return CacheHandler.GetBlogConfig(); }
   4:  }

Now, we can change the javascript reference up above to this cleaner version:
   1:  <script type="text/javascript" src='https://www.google.com/jsapi?key=
   2:  <%: Model.blogConfig.GoogleApiKey %>'></script>

We’re going to continue making a few more changes to our site master’s head element:
   1:  <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title>    
   2:  <asp:ContentPlaceHolder ID="MetaContent" runat="server" />
   3:  <script type="text/javascript" src='https://www.google.com/jsapi?key=
   4:  <%: Model.blogConfig.GoogleApiKey %>'></script>
   5:  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs
   6:  /jquery/1.4.4/jquery.min.js"></script>
   7:  <script type="text/javascript" src="https://ajax.googleapis.com/ajax
   8:  /libs/jqueryui/1.8.9/jquery-ui.min.js"></script>    
   9:  <script language="javascript" type="text/javascript" src="
  10:  <%= Url.Content("~/Scripts/watermark/jquery.watermark.min.js") %>"></script>
  11:  <script language="javascript" type="text/javascript" src="
  12:  <%= Url.Content("~/Scripts/highslide/highslide-with-gallery.min.js") %>"></script>
  13:  <script language="javascript" type="text/javascript" src="
  14:  <%= Url.Content("~/Scripts/site.js") %>"></script>
  15:  <link rel="stylesheet" type="text/css" href="
  16:  <%= Url.Content("~/Scripts/highslide/highslide.css") %>" />    
  17:  <%= Model.blogConfig.WebStatsJavascript %>
  18:  <%= Model.blogConfig.HeaderScript %>


This is everything in the head but we’ll just cover the new stuff.  Line 2 is a new Content Place Holder that we’ll use for meta data.  This way we can inject things like the page description and keywords into the page based on the content (i.e. so the keywords for a certain blog entry are specific to it’s content).  Lines 9 through 12 are for loading up the Highslide javascript library and the jQuery Watermark library.  Lines 13 and 14 are just to load up our site.js which we’ll put all or most of our site’s javascript into (later on we should probably change this to use  a minimized version).  15 and 16 are for the Highslide css file.  Lastly 17 and 18 bind to stuff we have in the Blog Config.  Specifically, whatever javascript we want to load for analytics or statistics (Google Analytics) and any javascript we want to store in the database (this way we can make quick and global script changes).

We’ve already done quite a bit and we haven’t even gotten to anything that actually shows up in the UI!  Let’s do one more config related thing and then actually start making our UI.  The last thing I want to do before doing some visual stuff is add a way for us to load a custom CSS file.  The idea is that eventually we’ll want to give users the ability to change between CSS files from the admin portal and alter the appearance of their site.  So, let’s add this to our head:

   1:  <link href="<%= Url.Content("~/Content/Themes/" + 
   2:  Model.blogConfig.Skin + ".css") %>" rel="Stylesheet" type="text/css" />


Again we’re pulling from the BlogConfig.  Now we want to have a default in case of the Skin not being set.  However, instead of specifying that here in the UI, we’ll go to the BlogConfig class and change it from an Automatic Property to something with a little logic:

   1:  private string _skin;
   2:  public string Skin
   3:  {
   4:      get { return (String.IsNullOrEmpty(_skin) ?  "Default" :  _skin); }
   5:      set { _skin = value; }
   6:  }

Now we’ll always get “Default” if something isn’t set.  For our UI, we’re going to go with a 2 column Fixed Fixed layout with the content column on the left and the menu column on the right.  The html for this is actually pretty simple:

   1:  <div id="maincontainer">        
   2:     <div id="topsection">            
   3:        <div class="innertube">            
   4:        <p id="logo">                        
   5:        </p>
   6:        <h1 class="titleOnlyHeader">
   7:           <%= Model.blogConfig.Title %>
   8:        </h1>
   9:        </div>
  10:     </div>
  11:     <!--  Legacy support for rounded corners -->
  12:     <b class="rtop"><b class="r1"></b>
  13:     <b class="r2"></b><b class="r3"></b><b
  14:     class="r4"></b></b> 
  15:     <div name="contentwrapper" id="contentwrapper">                              
  16:        <b style="background:#000;height:2px;display:block;width:700px;margin-left:30px;"></b>
  17:        <div id="contentcolumn">                                
  18:           <div class="innertube">                    
  19:              <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server" />                                            
  20:           </div>
  21:        </div>
  22:     </div>
  23:     <div id="rightcolumn">
  24:        <b style="background:#000;height:2px;display:block;width:170px;"></b> 
  25:        <b class="leftMenuBar"></b>
  26:        <div class="innertube" >
  27:        </div>
  28:     </div>           
  29:     <div id="footer">
  30:        <p>
  31:           <%= Model.blogConfig.CopyrightText%>
  32:        </p>
  33:     </div>                    
  34:  </div>    


There are a couple things to point out here.  At the top there is a P tag for a logo and then a h1 header tag with the class titleOnlyHeader in it.  The idea is that in general we’ll put a logo and the title into the Logo tag and then hide the titleOnlyHeader tag.  If we don’t have a logo though, we can just leave the titleOnlyHeader with the title as visible.  Right above ContentWrapper there is a section that will handle rounding the corners at the top of our main content area.  We might change this down the road to use jQuery but for now, we’ll stick with a css only solution.  The rest of it is more straight forward.  ContentColumn will contain all of our actual content.  The MainContent place holder is where all of the blog entries and page content will end up.  Then we have our RightColumn which will be our menu, links, etc.  Of course all of this is dependent on the CSS that will actually make things look the way we want them to.  Instead of going through all of our CSS (cause there is a fair amount) you can just look at it in the below attached code. 

That’s all we’re going to do for today.  We only got to a little bit of the actual UI, but we did handle a lot of set up.  Next time we’ll actually start putting some content into the site.  As always, the latest code is available here.

Bookmark and Share
First Article






Categories