Chris Risner . Com

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

Veritas – Designing the UI – Part 10

Posted on: 2/2/2011 7:40:00 PM by

Now that we’ve shown how to incorporate MetaWeblog API, we’re able to get data into our blog.  This means that once we actually have a UI around our site, we can actually show off our blog.  So today’s entry is going to create our basic UI.  Important to note is that we’re not going to do anything REALLY fancy.  Meaning that we’re not going to create any awesome templating engine or make it super easy to change the UI through any sort of administration engine.  Hopefully we’ll do this down the road (so you wouldn’t have to mess with CSS if you wanted to change how the site looks or where different elements appear) but that’s beyond the scope of this entry.

 

The first thing we’re going to do is lay a few ground work pieces.  Specifically, we need to add some folders beneath our Web projects Views folder.  Then we’re going to create our master pages.  Specifically we’re going to need a folder for the Admin section, the Blog section, and our home section.  Then we’ll need both Admin and Site master pages.  As you can see from the screenshot, we also have a Forum folder and Forum master page.  We’re not going to do anything with these for a while yet but eventually we’ll add a forum to the engine.

 

We aren’t going to do anything to the master pages yet, except add some links to the javascript files we’ll use.  For now, we’re just going to add references to JQuery and JQueryUI.  Now, we could easily grab the latest version of these scripts and plop them into our scripts folder.  However, wouldn’t it be nice if we could just let someone else host these files?  Someone that was capable of hosting tons of data and serving it up quickly and efficiently?  Thankfully, Google is going to help us out here.  After requesting an API key, you can load up several different javascript files without having to worry about it yourself.  Here is what we’ve put in the head section of our master pages:

   1:  <script type="text/javascript" src='https://www.google.com/jsapi?key=<%: 
(ViewData["BlogConfig"] as BlogConfig).GoogleApiKey %>'
></script>
   2:  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/
jquery/1.4.4/jquery.min.js"
></script>
   3:  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/
jqueryui/1.8.9/jquery-ui.min.js"
></script>

Here, we’re loading the primary google javascript API file with an API key we get from the blog config.  Then we’re just loading up the JQuery and JQueryUI libraries.

Blog Home ScreensWe’re going to tie all of our Views directly to screen objects (or View Models if you prefer).  We could create our view files, and then our screen objects, but then we’d have to manually change the inherit Page Directive in each page.  We aren’t going to create every single screen object we’ll need right now, but we’ll create the majority of what we’ll need for the public portion of the site.  Just like we did for the Views, we’ll create subfolders in our BusinessLayer’s screens folder for Admin, Blog, and Home.  First and foremost, we’ll create the Screen objects for our Home views.  We’re going to need an About page, a Contact Us page, and a Home page.  We’re also going to have a page to make it easier to upload files, a generic page for displaying messages, and a page to display generic data we store in the database (think of it like the ability to create add an html page to our website where the content is stored in the database.  So if someone went to ViewContent/Page1, they’d get whatever html we stored in the database for Page1).  For now we’re just going to create Screen objects for all of those and make them inherit from our screen base.  All of these screen objects will descend from the ScreenBase abstract class we added earlier.  For now, we’ll add the methods and properties we’re required to implement from ScreenBase (IsValid and LoadScreen).  We won’t implement these until we’re actually ready to.  We’ve got a lot of other screen objects to create but for now, we’ll jump over to views.

New ViewTo start, we’ll just create our Home views.  So beneath the Home folder, let’s add the Index view.  When you go to add a new View, you’ll be able to name it (in this case just “Index”) and then we can decide if we want to strongly type the View.  There’s nothing requiring you to strongly type your view to an object.  However, we’re gong to do this directly to our screen objects.  As we’ll see when we get to actually putting stuff on our Views, being strongly typed will make things much easier.  After checking the “strongly-typed view” checkbox, we’ll be able to select our Home.IndexScreen.  After picking our data class, we can select what type of View Content the page will be (Create, Delete, Details, Edit, Empty, List).  If we were binding to an actual Model we might choose something other than Empty, which is what we’ll choose now.  Since we haven’t put anything interesting into any of our Screen objects, choosing something else wouldn’t really help us much.  What get’s created is a very basic view.  All it has is the Page directive line and a little html.  One thing we’re going to have to immediately change is the Inherit’s line in the Page directives.  Right now it’s descending from a System.Web.Mvc.ViewPage. 

Inherits="System.Web.Mvc.ViewPage<Veritas.BusinessLayer.Screens.Home.IndexScreen>"

This is fine for normal sites.  However, we created a VeritasViewPage we want all of our pages to descend to.  So this will now become:

Inherits="Veritas.UI.Web.Views.VeritasViewPage<Veritas.BusinessLayer.Screens.Home.IndexScreen>"

dfdsJust like in the Master pages, this will just give us access to our VeritasForm class in our View. 

Next we’ll create a HomeController class in our Controllers folder.  This will inherit from a ControllerBase class.  The ControllerBase in turn, will inherit from the MVC controller class and will give all of our controllers access to things like our data repository, our BlogConfig, MenuItems, Authentication and Login data in addition to handling unknown actions.  To our HomeController we’ll just add some base ActionResult methods to load our views:

   1:  public ActionResult About(){
   2:      return View();
   3:  }
   4:          
   5:  public ActionResult Contact()
   6:  {
   7:      return View();
   8:  }

Now we’re able to load our views. Well, we’re kind of ready.  If you were to run exactly what we’ve got right now, you’d run into a few issues.  Some of them make sense and others seems like they shouldn’t be issues.  First and foremost, in order for our Master pages to understand what the BlogConfig class is without using the full namespace (how we’re using in the first javascript reference above), we need to import the namespace into the view.  This can be thought of as being similar to a using statement in the cs file.  We need to reference the Models namespace like so:

<%@ Import Namespace="Veritas.DataLayer.Models" %>

Now instead of saying Veritas.DataLayer.Models.BlogConfig, we can just use BlogConfig.  Next we’re going to run into a problem with referencing an “Entity” in the Web project.  The exception you’ll get will be this:

error CS0012: The type 'System.Data.Objects.DataClasses.EntityObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

So, we’ll add the reference for System.Data.Entity to our web project.  However, we’ll still get this error after adding the reference.  The assembly needs to be added into the assemblies node in our web.config like so:

<add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

This will fix the problem.  Now things will load correctly and we’ll get to our Index page.  However, if you were to watch the BlogLog table or put a breakpoint in the Application_Error() in the Global.asax.cs, you’d see we’re getting 404 errors.  What could be causing this?  We’re not loading anything in our index view or our Master page.  However, if we look closer at the error, we realize that something is automatically requesting something from our site: the Favicon.  If you read here, you’ll see that browsers don’t need any html to automatically request and load a site’s favicon.  So even though we’re returning a 404 right now, we don’t need to actually fix the problem for the site to work.  We’ll go ahead and add one now.  We’ve got a lot of work left for the UI, but for now, we’ve made a lot of progress so we’ll leave it off here.  You can check out the latest code here.

Bookmark and Share
First Article

Debugging in Visual Studio 2005 on Windows 7 and IE8

Posted on: 5/11/2010 12:48:00 PM by

FAIL The team I’m on at work recently took over maintenance on a number of older projects, some of which were never upgraded out of Visual Studio 2005.  The first thing I did for one of them was convert the solution to VS2008.  Unfortunately we didn’t have the time or the resources to do a full integration test and make sure the upgrade didn’t break any existing functionality.  So while my conversion would insure we’d at least be using a relatively recent version of Visual Studio (upgrading all the way to 2010 wasn’t really an option at the moment) we couldn’t do it.  That’s fine as we were going to be rewriting the whole thing sooner or later. 

Yesterday I finally started doing some work in VS2005.  As painful as it was, most of the issues were things I couldn’t really complain too much about.  It wasn’t like I expected Microsoft to update VS2005 so it would run faster.  After making mostly text changes, I ran into something that actually required me to run the debugger.  I loaded it up and started testing my changes, however, none of my breakpoints were being hit.  I looked at VS2005 and the debug toolbar wasn’t there.  I restarted the debugger and noticed that the debug toolbar was disappearing right after the site started (though oddly IE was staying open).  After googling a good amount, I came across this article which explains that IE8 breaks the debugger in VS 2005.  According to the article, IE8 runs under multiple processes and VS2005 doesn’t know how to deal with this.  The easiest solution, and the first offered, is to close down IE before you start the debugger.  If you do that, then it will be able to figure out what it needs to attach to.  Another easy solution (not mentioned in the article) if you don’t want to have to close IE every time you want to debug is to manually attach the debugger to the instance of WebDev.WebServer.Exe that is running your site.

Poop While I rarely ever fire up VS2005, I’m sure there are some shops out there that are still using it pretty heavily.  This seems like something that should have been patched by now or at least a little bit easier to find the solution to online.  Since Microsoft pushes IE8 via the Windows Updates as a required update, it would seem to me that they would also add a fix for Visual Studio.  

Categories: .Net, Visual Studio, Web
Bookmark and Share
First Article






Categories