Steve Moseley

"To err is human. To really screw up takes a computer." - Dilbert

Syndicating RSS in an ASP.Net MVC app using WCF

clock December 15, 2009 15:26 by author steve

About a month back Rob Conery mentioned that he was going to create a blogging application using MVC, which caused me to think to myself: “SELF! why don’t you try something like that and see what you can come up with?”  So in my spare time when I am not doing real work or at home shuttling kids around, I’ve been playing around with this idea.  I am really happy with my BlogEngine.Net set up and probably will continue to use it even if I were to finish this app but I figure this would be an opportunity to just do something different than I have been doing lately and learn some new things that I have not had a chance to work with as of yet.

So with that in mind, one of the first things I decided to tackle was going about syndicating an RSS feed and as it turns out it is not too terribly difficult to do; although, there are some things I did struggle with—uhhh---but I am getting ahead of myself.

Build you own ActionResult

I mention in my previous post that ASP.Net come with several different controller actions, and the one that I used in the that example was the JsonResult.  Well JsonResult really is just a class that is derived from the abstract class ActionResult.  I can write my own class that derives from ActionResult to return back to the view an RSS feed which is what I am going to do in this example.

   1: using System.ServiceModel.Syndication;
   2: using System.Web.Mvc;
   3: using System.Xml;
   4:  
   5: namespace Aviblog.Core.ActionResults
   6: {
   7:     public class RssResult : ActionResult
   8:     {
   9:         private readonly SyndicationFeed _feed;
  10:  
  11:         public RssResult(SyndicationFeed feed)
  12:         {
  13:             _feed = feed;
  14:         }
  15:  
  16:         public override void ExecuteResult(ControllerContext context)
  17:         {
  18:             context.HttpContext.Response.ContentType = "application/rss+xml";
  19:             var formatter = new Rss20FeedFormatter(_feed);
  20:  
  21:             using (XmlWriter writer = XmlWriter.Create(context.HttpContext.Response.Output))
  22:                 if (writer != null) formatter.WriteTo(writer);
  23:         }
  24:     }
  25: }

So in my custom RssResult that inherits from ActionResult, I need to then override the ExecuteResult method.  Inside that method I then need to set the response type to “application/rss+xml” so it can be rendered as RSS.  The next thing to notice is that in my constructor I am passing in an object of type SyndicationFeed which is a part of WCF.  It is in the System.ServiceModel.Syndication namespace.  You can find it by referencing the System.ServiceModel.Web assembly.  I can then use the Rss20FeedFormatter to generate XML which is RSS compliant.

 

Building the SyndicationFeed

Building the SyndicationFeed object is where I had the most trouble. If you just want a simple compliant RSS feed, this guy works great; however, as you can see just from looking at my own RSS feed there many other elements you can extend to an RSS feed and adding those to the SyndicationFeed element is a bit tricky.

   1: public SyndicationFeed Buildfeed()
   2:         {
   3:             var settingQry = _settingsRepository.GetSettings();
   4:             const string nameKey = "name";
   5:             const string nameDescription = "description";
   6:             const string link = "link";
   7:             string blogTitle = _settingsService.GetValue(settingQry, nameKey);
   8:             string blogDescription = _settingsService.GetValue(settingQry, nameDescription);
   9:             Uri blogUrl = _settingsService.GetUri(settingQry, link);
  10:  
  11:             var feed = new SyndicationFeed(blogTitle, blogDescription, blogUrl);
  12:  
  13:             foreach (var element in _feedRepository.GetFeedElements())
  14:                 feed.ElementExtensions.Add(BuildXmlElement(element));
  15:  
  16:             feed.Items = LoadPosts(_postService.GetMostRecentPosts());
  17:             return feed;
  18:         }
  19:  
  20:         private static XmlElement BuildXmlElement(FeedElementDto element)
  21:         {
  22:             var doc = new XmlDocument();
  23:             XmlElement feedElement = doc.CreateElement(element.Prefix, element.Element, element.Namespace);
  24:             feedElement.InnerText = element.InnerText;
  25:             return feedElement;
  26:         }

From the code you can see that when I am instantiating the SyndicationFeed object I am passing in the title of the blog, the blog description, and the URL.  Where it got a bit hairy, was adding other elements that prefixed a common namespace.  I could add the namespace for each element (as seen in the code) but there does not seem to be a way to put the common namespaces in say the channel element and then just use the prefix to those namespaces later. I ended up having to repeat the same namespaces over again.  But that being said, it is still pretty easy to build the feed.

Once the feed object is ready I then could add each of the posts by mapping them to a SyndicationItem object and then add those collection of objects to the items collection in the feed.

   1: private static IEnumerable<SyndicationItem> LoadPosts(IEnumerable<PostDto> posts)
   2:         {
   3:             IList<SyndicationItem> items = new List<SyndicationItem>();
   4:             foreach (var post in posts)
   5:             {
   6:                 var item = new SyndicationItem();
   7:                 item.Title = new TextSyndicationContent(post.Title);
   8:                 item.Authors.Add(new SyndicationPerson(post.Author));
   9:                 item.Content = SyndicationContent.CreateHtmlContent(post.PostContent);
  10:                 items.Add(item);
  11:             }
  12:             return items;
  13:         }

 

The Controller Class

Now that I have my RssResult and my functionality to build the SyndicationFeed object, I can then create an action inside my controller class that puts the two together.

   1: public class SyndicationController : Controller
   2:     {
   3:         private readonly IRss20SyndicationService _rss20SyndicationService;
   4:  
   5:         public SyndicationController(IRss20SyndicationService rss20SyndicationService)
   6:         {
   7:             _rss20SyndicationService = rss20SyndicationService;
   8:         }
   9:  
  10:         public RssResult Rss()
  11:         {
  12:  
  13:             return new RssResult(_rss20SyndicationService.Buildfeed());
  14:         }
  15:     }

 

The Result

So when I browse to domain/controller/action in this case http://localhost:64533/Syndication/Rss I get the following RSS sample:

 

   1: <?xml version="1.0" encoding="utf-8"?>
   2: <rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">
   3:   <channel>
   4:     <title>Steve Moseley</title>
   5:     <link>http://www.test.com/</link>
   6:     <description>Trying my best to apprehend all these dev changes.</description>
   7:     <blogChannel:blogRoll xmlns:blogChannel="http://backend.userland.com/blogChannelModule">http://www.avingtonsolutions.com/blog/opml.axd</blogChannel:blogRoll>
   8:     <blogChannel:blink xmlns:blogChannel="http://backend.userland.com/blogChannelModule">http://www.dotnetblogengine.net/syndication.axd</blogChannel:blink>
   9:     <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Steve Moseley</dc:creator>
  10:     <dc:title xmlns:dc="http://purl.org/dc/elements/1.1/">Steve Moseley</dc:title>
  11:     <geo:lat xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">0.000000</geo:lat>
  12:     <geo:long xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">0.000000</geo:long>
  13:     <item>
  14:       <author>Steve</author>
  15:       <title />
  16:       <description>
  17:        blah, blah, blah
  18:       </description>
  19:     </item>
  20:   </channel>
  21: </rss>

 

Looks pretty good, although, if you look at my actual RSS feed and this one, you will notice that the name spaces are repeated verses being listed at the top as they probably should be.  I need to play around with it some more but this gets the job done and I did not have to write all that much code, which is nice.



Filtering Dropdowns in a ASP.Net MVC App using jQuery and jSon.

clock October 24, 2009 14:39 by author Steve

I have often come across the need to load a dropdown list based on the selection of another drop down list on a form.  In web forms it is really easy, especially if you were just doing a regular page post back.  You simply set the dropdown’s AutoPostBack property to true and then on the change event load the second dropdown based on the value of the first event.

Then along came the Ajax Toolkit that had Ajax server controls that would basically do that for you pretty simply without a full page postback.  You could see a demo of that functionality here.

How to do this with MVC

Now in MVC all the cool server controls are gone but with just a little extra work we can get the same functionality pretty easily.  Moreover, using the Json protocol makes the population of the second drop down much lighter accross the wire.

In my example, I have a pretend scenario where the user selects an event from the first drop down and based on the value of the first selection, the options of the second is dropdown is populated.

Here is the view code I am using for this example. (Note: I am using the Sparks View Engine for the View Framework instead of the Microsoft MVC View Framework because it makes the mark up much cleaner.

   1: <viewdata EventList="SelectList" />
   2:  
   3:  
   4: <content name="head">
   5:     <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min-vsdoc.js" type="text/javascript"></script>
   6:     <script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.js" type="text/javascript"></script>
   7: </content>
   8:  
   9:  
  10:  
  11:  
  12: #using (Html.BeginForm())
  13: #        {
  14:           
  15:  <div>
  16:             <fieldset>
  17:                 <legend>Event Information</legend>
  18:                 <p>
  19:                     <label for="eventname">Event name:</label>
  20:                     ${Html.DropDownList("eventname", EventList)}
  21:                 </p>
  22:                 <p>
  23:                     <label for="eventdate">Event Date:</label>
  24:                     <select id="eventdate">
  25:                         <option value="">Select Date:</option>
  26:                     </select>
  27:                 </p>
  28:                 <p>
  29:                     <input type="submit" value="See Event Info" />
  30:                 </p>
  31:             </fieldset>
  32:         </div>         
  33:           
  34:           
  35: #}

 

If you are wondering why my second selection list is not generated by the HtmlHelper class it is only because I was not able to append to it using jQuery.  Since it really wasn’t needed anyway I just decided not to bother.

The name of my view is called Events and it resides in my Home controller and the code for populates that view looks like this.

   1: public ActionResult Events()
   2:         {
   3:             IList<EventDto> events = new List<EventDto>();
   4:             const int upper = 5;
   5:             for (int i = 0; i < upper; i++)
   6:             {
   7:                 var eventItem = new EventDto() {EventCode = i.ToString(), Eventname = string.Format("Name {0}", i)};
   8:                 events.Add(eventItem);
   9:             }
  10:  
  11:             var eventList = new SelectList(events, "EventCode", "EventName");
  12:             ViewData["EventList"] = eventList;
  13:             return View();
  14:         }

 

Nothing special here.  I am just creating a list of events and then passing it to a SelectList so it can be populated in the view.

So when the page loads the HTML looks like this:

   1:  
   2:                 <legend>Event Information</legend>
   3:                 <p>
   4:                     <label for="eventname">Event name:</label>
   5:                     <select id="eventname" name="eventname"><option value="0">Name 0</option>
   6: <option value="1">Name 1</option>
   7: <option value="2">Name 2</option>
   8: <option value="3">Name 3</option>
   9: <option value="4">Name 4</option>
  10: </select>
  11:                 </p>
  12:                 <p>
  13:                     <label for="eventdate">Event Date:</label>
  14:                     <select id="eventdate">
  15:                         <option>Select Date:</option>
  16:                     </select>
  17:                 </p>
  18:                 <p>
  19:                     <input value="See Event Info" type="submit">
  20:                 </p>
  21:             

And the page looks like this:

page1

The JsonResult Function

ASP.Net MVC comes with different controller actions, one of them being the JsonResult action.  Like the ActionResult, the JsonResult sends data back to the view but in this case, the response is converted into JSON.

   1: [AcceptVerbs(HttpVerbs.Get)]
   2:         public JsonResult EventDates(string eventCode)
   3:         {
   4:             IList<EventDateDto> eventDates = BuildEventDates(eventCode);
   5:             return Json(eventDates);
   6:         }

In writing the function, first I have to tell it action to respond do.  In this case I want it to respond to “GET” requests, so I need to add the AcceptVerbs attribute to the function with the “GET” verb stated.  The function needs to have the parameter for the event code that the user selected in the dropdown, and then based on the parameter the application gets a list of dates.  These collection dates (are formatted as strings in this case) are then passed back by calling the Json() function.

 

The jQuery function:

So in order to get the data for the second dropdown we need to make an AJAX call to the server and pass it the value of the first dropdown when its “change” event is fired.

When the event is fired, we can then use the jQuery $.AJAX call to make a “GET” request to the URL as such:  …/Home/EventDates?eventCode=3.  When you look at the header of the request you also notice that “Accept” attribute is set to “application/json, text/javascript, */*”.

   1: <script type="text/javascript" charset="utf-8">
   2:         $(function(){
   3:           $("select#eventname").change(function(){
   4:                 var data = $(this).val();
   5:                 var json = {eventCode: data};
   6:                 
   7:                 
   8:                 $.ajax({
   9:                   type: "GET",
  10:                   url: "/Home/EventDates",
  11:                   data: json,
  12:                   dataType: "json",
  13:                   error: function(xhr, status, error) {
  14:                     alert("error routine");
  15:                   },
  16:                   success: function(res){
  17:                     var $dropdown = $("select#eventdate");
  18:                     $dropdown.find('option').remove().end();
  19:                     $dropdown.append('<option value="">Select Date</option>');
  20:                     for (var i = 0; i < res.length; i++) {
  21:                         $("select#eventdate").append('<option value="' + res[i].EventDateName + '">' + res[i].EventDateName + '</option>');
  22:                       }
  23:                       
  24:                   }
  25:                 });
  26:           });
  27:         })
  28:         </script>

Notice that the data we are passing must in the request must be in a jSon format.  So in the case the data we are passing is {eventCode:3}.  The response we get back is:

[{"EventDateCode":"10/27/2009","EventDateName":"10/27/2009"},{"EventDateCode":"10/30/2009","EventDateName":"10/30/2009"},
{"EventDateCode":"11/2/2009","EventDateName":"11/2/2009"},{"EventDateCode":"11/5/2009","EventDateName":"11/5/2009"},
{"EventDateCode":"11/8/2009","EventDateName":"11/8/2009"},{"EventDateCode":"11/11/2009","EventDateName":"11/11/2009"},
{"EventDateCode":"11/14/2009","EventDateName":"11/14/2009"},{"EventDateCode":"11/17/2009","EventDateName":"11/17/2009"},
{"EventDateCode":"11/20/2009","EventDateName":"11/20/2009"}]

 

If the response is successful, the callback function takes the collection that is returned and build a string of <option> tags and append it to the select object.

page1after

Update:

In the MVC 2 version the JsonResult response will by default throw an exception. This is because of a subtle vulnerability in which someone could gain access to sensitive information. You can get the details from Phil Haack's post. So the moral of the story is if you passing sensitive imformation in the response, it is probably better for you to make a POST rather than doing GET like I did in this example. If you are not passing sensitive information and you still would to use a GET request then you will need to change the JSon method from:

return JSon(eventDates);

to

return JSon(eventDates, JSonRequestBehavior.AllowGet);



Creating a Custom Trace Listener for WCF

clock June 15, 2009 11:00 by author Steve

Introduction

We have been using WCF to consume a lot of 3rd party web services, and one of things we depend on when testing is being able to see the actual request and response that is being sent to and from the host.  This is expecially inportant in 3rd party services, because the service is essentially a black box in which there is no way to know what is going on except that you send it a request and you get a response back.  I posted how, out of the box, you can configure WCF to write the message to a trace xml file, but one of things about writing to a file is that if you or your testers do not have access to the web server where the file is being written then this is not going to work.

Solution

The way around this problem is to create a custom trace listener that catches the messages and does what ever you want.  Here is a simple sample.

Create a class that inherits from the TraceListiner class.

    1 using System.Diagnostics;

    2 

    3 namespace WcfTrace.Trace

    4 {

    5     public class WebTraceListener : TraceListener

    6     {

    7         public override void Write(string message)

    8         {

    9             //write you custom code here

   10             Debug.WriteLine(message);

   11         }

   12 

   13 

   14         public override void WriteLine(string message)

   15         {

   16             //write your custom code here

   17             Debug.WriteLine(message);

   18         }

   19     }

   20 }

The next thing to do is to wire up the custom class in the web.config (or app.config) so that when messages are created ,they caught by the custom trace listener class.  The config below is telling source messages to use the sharedListener named xml which the custom trace listener listed above.

  108   <system.diagnostics>

  109     <sources>

  110       <source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">

  111         <listeners>

  112           <add name="xml" />

  113         </listeners>

  114       </source>

  115       <source name="System.ServiceModel.MessageLogging">

  116         <listeners>

  117           <add name="xml" />

  118         </listeners>

  119       </source>

  120     </sources>

  121     <sharedListeners>

  122       <add name="xml" type="WcfTrace.Trace.WebTraceListener,WcfTrace.Trace" />

  123     </sharedListeners>

  124   </system.diagnostics>

  125 

  126   <system.serviceModel>

  127     <diagnostics>

  128       <messageLogging

  129           logEntireMessage="true"

  130           logMalformedMessages="false"

  131           logMessagesAtServiceLevel="true"

  132           logMessagesAtTransportLevel="false"

  133           maxMessagesToLog="300000"

  134           maxSizeOfMessageToLog="200000"/>

  135     </diagnostics>

That's it.  Now when ever a web service call is made, the custom trace listener class is executed, passing it the trace messages.



Entity Framework 4.0 Sneak Peak - POCO Goodness!

clock May 12, 2009 04:09 by author Steve

A while back I posted that I was looking into the viability of using Entity Framework, and at the time I was genuinly excited about what it had to offer. I even stated that I would report back to you my findings.  So I set out to try and create a domain layer that used EF as an O/R Mapper but also tried maintained percistance ignorance with the data objects it was passing around.  Percistance Ignorance being the objects containing the data retrieved from the database should not contain any information about the mechanism it used to retrieve the data.

To be honest, I was pretty disappointed with my findings. Entity Framework 3.5 is pretty intrusive.  All data objects had to either impliment an EntityFramework interface or had to be a subclass of an EntityObject class.

I never went back and revisited that blog post, mainly because I did not want to spew vile about the product; so I just let it be and started looking into nHibernate.  I was sort of down because all the good tools like LightSpeed cost money.

Well now it looks like Microsoft has heard our gripes about the products short comings and is going to do something about it.

You can read all about it here.

 



MVC and Thumbnails with StructureMap

clock May 2, 2009 13:47 by author Steve

In the process of looking for a way to read large images from a file or database, and displaying them as thumbnails, while all the while doing this using the MVC framework and TDD; I came accross two really good blog samples.  One by Josh Holmes and the other approach by Tom Janssens.  I took the latter example, and it worked like a charm.

The only I change I made was to refactor the singleton function that retrieves the MemoryStream so that I can test it.  I used StructureMap in this case so I could inject it into the ThumbNail class.  Therefore the GetMemoryStream function which was static so it could used as a singleton was moved to it's own class.

Here is the interface:

    7     public interface IImageMemoryManager

    8     {

    9         MemoryStream GetStream(Image image, int width, int height, ImageFormat imageFormat);

   10     }

The function in the sample that converts the image into a MemoryStream will then located in the concreate class ImageMemoryManager which impliments the above function.

On the Application_Start event of my application, I can call out to a bootstrapper class that loads up StructureMap mappings and saves it so it can be used later.

   28         protected void Application_Start()

   29         {

   30             RegisterRoutes(RouteTable.Routes);

   31             BootStrapper.ConfigureStructureMap();

   32             ControllerBuilder.Current.SetControllerFactory(new GalleryControllerFactory());

   33         }

The Bootstrapper class configures the StructureMap mappings.

    6     public class BootStrapper

    7     {

    8         public static void ConfigureStructureMap()

    9         {

   10             StructureMapConfiguration.AddRegistry(new StructureMapSiteRegistry());

   11         }

   12     }

 And here is mappings: 

    9     internal class StructureMapSiteRegistry : Registry

   10     {

   11         protected override void configure()

   12         {

   13             ForRequestedType<IContentType>().TheDefaultIsConcreteType<ContentType>();

   14             ForRequestedType<IPictureRespository>().TheDefaultIsConcreteType<SqlPictureRespository>();

   15             ForRequestedType<IImageMemoryManager>().TheDefaultIsConcreteType<ImageMemoryManager>().CacheBy(

   16                 InstanceScope.Singleton);

   17         }

   18     }

Notice the IImageMemoryManager maps to the contrete class ImageMemoryManager, and since initially it was a singleton class; I want to designate the mapping's InstanceScope as Singleton by using the CacheBy function.

 I can then inject the these mappings into all my controller by inheriting from the DefaultControllerFactory class calling the GetInstance function in StructureMap to build out the injections. 

    7     public class GalleryControllerFactory : DefaultControllerFactory

    8     {

    9         protected override IController GetControllerInstance(System.Type controllerType)

   10         {

   11             IController result = null;

   12             if (controllerType != null)

   13             {

   14                 try

   15                 {

   16                     result = ObjectFactory.GetInstance(controllerType) as Controller;

   17                 }

   18                 catch(StructureMapException ex)

   19                 {

   20                     Debug.WriteLine(ObjectFactory.WhatDoIHave());

   21                 }

   22             }

   23             return result;

   24         }

   25 

   26     }

By the way, you can get a real good sample code to this by taking a look at the MvcContrib samples. 

Now I that the function is isolated I can test it.

   72         [TestMethod()]

   73         public void GetStreamTest()

   74         {

   75             ImageMemoryManager target = new ImageMemoryManager(); // TODO: Initialize to an appropriate value

   76             Image image = Image.FromFile(@"C:\Projects\Gallery\source\Gallery.Tests\Images\shuttle5-768.jpg");

   77             int width = 100;

   78             int height = 100;

   79             ImageFormat imageFormat = ImageFormat.Bmp;

   80 

   81             MemoryStream actual = target.GetStream(image, width, height, imageFormat);

   82             Assert.IsNotNull(actual);

   83         }

I could probably put together a more rigorous test here, but its testable.

The ThumbNailResults class which is returned to the view now looks like this.

   10     public class ThumbnailResult : FileStreamResult

   11     {

   12 

   13 

   14         public ThumbnailResult(Image input) : this(input, input.Width, input.Height)

   15         {

   16         }

   17 

   18         public ThumbnailResult(Image input, int width, int height) :

   19             base(

   20             ((IImageMemoryManager) StructureMap.ObjectFactory.GetInstance(typeof (IImageMemoryManager))).GetStream(

   21                 input, width, height, ImageFormat.Png),

   22             "image/png")

   23         {

   24         }

   25 

   26 

   27 

   28 

   29     }

Thanks to Tom and Josh in providing really nice examples.  It's nice to see the community contributing with really good examples to such a new framework!

 

 

 

 

 

 

 

 



ASP.Net MVC 1.0 and Resharper 4.5 Beta released

clock March 18, 2009 05:05 by author Steve

Wow! It's an exciting week to be a dot net developer. 

The long awaited official version of ASP.NET MVC was released during MIX 09.  As far as getting up to speed, there is a butt-load of stuff on the ASP.Net website.

 Also, those of us who cannot write a line code without Resharper will be happy to know the 4.5 beta is out which segnificantly improves its performance.  That being one of my big gripes about the product, especially when you try and run it in a virtual environement with big solutions, am really excited to take this new edition out for a drive.  You can see the details about it here.



AAA and Rhino.Mocks

clock March 4, 2009 08:57 by author Steve

FYI:  After watching this dimecasts video, I realized that you no longer have to use the Record() Playback() routines, you just have to use the extension method Expect.

 

So instead of:

 

var mock = new MockRepostitory();

var foo = mock.StrickMock<IFoo>();

 

 

using (mock.Record())

{

     Expect.Call(foo.DoSomething()).Return(something);

}

using (mock.Playback())

{

     var fooB = new FooB(foo);

     bool result = fooB.IsSomething();

     Assert.IsTrue(result);

}

 

 

The code to mock is:

 

var foo = MockRepository.GenerateMock<IFoo>();

foo.Expect(x => x.DoSomething()).Return(something);

var fooB = new FooB(foo);

bool result = fooB.IsSomething();

Assert.IsTrue(result);



Creating a Web Application Using MVC, Unity and NHibernate – Part 3: Mocking

clock January 30, 2009 02:04 by author Steve

This is the third post in the series.  You can see the other to posts here:

The Service Layer

Now that I have a data layer, I would like to create a service layer that takes the records retrieved from the database and then applies the business rules to them.  Some of these rules are that I would like to apply are:

  • I would only like to show the first 5 most recent posts on the home page.
  • I would like catch any exceptions and log them.

If I was not testing this function first, my code would look something like this.

   37         public List<NewsItemDto> GetLatestNewsItems(int numberOfItems)

   38         {

   39             List<NewsItemDto> items;

   40 

   41             try

   42             {

   43                 using (ISessionFactory sessionFactory = (new Configuration().Configure().BuildSessionFactory()))

   44                 {

   45 

   46                     using (ISession session = new object() as ISession)

   47                     {

   48                         var provider = new NHibernateDataProvider(session);

   49                         var result = provider.GetAllPublishedFrontPagePosts();

   50                         items = result != null ? result.OrderByDescending(i => i.DatePublished).Take(5).ToList() : null;

   51                     }

   52                 }

   53             }

   54             catch (Exception ex)

   55             {

   56                 ExceptionPolicy.HandleException(ex, "General");

   57                 throw;

   58             }

   59 

   60             return items;

   61 

   62         }

 

Here are some of the issues with this method.

  • The method is depending on the NHibernateDataProvider class.  This means I have to have a database setup for this test.  If I have a lot of service layer tests connecting to the database then these tests are going to take forever to run.
  • Another issue with being dependant on the NHibernateDataProvider class is now I have to some way to create an ISessionFactory class.
  • For logging errors, I have a dependency on using Microsoft Exception Handler class so if I ever want to change that logging plumbing I have to change it all over my app.

·          In general there is a lot of stuff happening but really all I want to test is getting a list of news items that match the count I want and are sorted in the correct order.

The Test

Okay, so back to the drawing board.  Let me start with the test first and see if I can test this function without having it connect to a database. To do this I am going extract the interface for the NHibernateDataProvider class and call it IDataProvider.

    7     public interface IDataProvider

    8     {

    9         IQueryable<NewsItemDto> GetAllPublishedFrontPagePosts();

   10         NewsItemDto GetNewsItemByItemId(long newsItemId);

   11         IList<AuthorDto> GetAuthorsBy(string userId);

   12     }

 

In this example, I am using the Microsoft Enterprise Library Exception Policy class for logging exceptions.  This class is sealed with one static method class called HandleException.  Because of this, I cannot extract an interface, so for now I am going wrap this class in another concrete class that implements an interface that I can inject.

The interface looks like this:

    5     public interface ILogger

    6     {

    7         void LogException(Exception ex);

    8     }

 

The derived concrete class looks like this:

    6     public class MicrosoftLogger : ILogger

    7     {

    8         public void LogException(Exception ex)

    9         {

   10             ExceptionPolicy.HandleException(ex, "General");

   11         }

   12     }

 

Now I can mock my data provider and my logging class in my test, and I can also inject these classes into my web application later on.

So now the constructor of my service class looks like this:

   12     public class NewsItemService : INewsItemService

   13     {

   14         private readonly IDataProvider newsDataProvider;

   15         private readonly ILogger logger;

   16 

   17         public NewsItemService(IDataProvider newsDataProvider, ILogger logger)

   18         {

   19             this.newsDataProvider = newsDataProvider;

   20             this.logger = logger;

   21         }

 

So I mentioned that I am going mock the data provider class and to do this I am going use my mock tool of choice Rhino.Mocks.

   74         [TestMethod()]

   75         public void NewsItemService_get_latest_news_items_should_return_5_most_recent()

   76         {

   77             var mockRepository = new MockRepository();

   78             var dataProvider = mockRepository.StrictMock<IDataProvider>();

   79             var mockLogger = mockRepository.StrictMock<ILogger>();

   80 

   81             using (mockRepository.Record())

   82             {

   83                 Expect.Call(dataProvider.GetAllPublishedFrontPagePosts()).Return(PostRepository.GetNewsItems());

   84             }

   85 

   86             var numberOfItems = 5;

   87             var expected = 5;

   88             using (mockRepository.Playback())

   89             {

   90                 var target = new NewsItemService(dataProvider, mockLogger);

   91                 var items = target.GetLatestNewsItems(numberOfItems);

   92                 var currentDate = DateTime.MaxValue;

   93 

   94                 foreach (var item in items)

   95                 {

   96                     Assert.IsTrue(currentDate > item.DatePublished, currentDate.ToShortDateString() + " is not > " + item.DatePublished.ToShortDateString());

   97                     currentDate = item.DatePublished;

   98                 }

   99 

  100                 Assert.AreEqual(items.Count, expected, "Get the latest news does not eaqual 5");

  101             }

  102 

  103         }

 

In the test above instead of connecting to the database, I first tell Rhino Mocks to mock my data provider.  I pass it the IDataProvider interface and Rhino Mocks gives me back an instantiated data provider even though there is now derived concrete class involved.  I then do the same for the logging object.

In the Record section, I am telling Rhino Mocks that later on when I actually test my service object to expect it to make a call to the data provider class with a specific set of parameters (in this case I have no parameters) and when this occurs return my mocked result.  Once I have recorded all my expected calls that I want to mock, I can then proceed to the Playback method to test my service.

Inside the Playback I write my test as if I was actually connecting to a database and I assert that I got back 5 records sorted by the published date.

So I test and my test fails because I have not implemented the GetLatestNewsItems yet so let me do that.

   23         public List<NewsItemDto> GetLatestNewsItems(int numberOfItems)

   24         {

   25             try

   26             {

   27                 var items = newsDataProvider.GetAllPublishedFrontPagePosts();

   28                 return items != null ? items.OrderByDescending(i => i.DatePublished).Take(5).ToList() : null;

   29             }

   30             catch(Exception ex  )

   31             {

   32                 logger.LogException(ex);

   33                 throw;

   34             }

   35         }

 

Now I can test my object without being dependant on any concrete classes, and I can also inject my dependencies later on using Unity.

In my next post I will look into testing my controller class and some of the features MVC provides to do controller unit testing.


Creating a Web Application Using MVC, Unity and NHibernate – Part 2 nHibernate

clock January 24, 2009 06:00 by author Steve

Introduction

In the last post I set up NHibernate and created a simple test to retrieve one record from the database.  Now I would like to join the News table and Author table together and then create a test to see if I can successfully retrieve a record that contains both data from both tables joined together.

If you recall my schema looks like this:

 

 

 

 

So the first thing I would like to do is change create the mapping and DTO class for the Author table, but before I can do that, I need to add a reference of the Iesi.Collections.dll external assembly to my projects so I can create the ISet<> collection object.  Since one author can have many news items, my author class will have a collection of news items.  Since each of these news items must be unique, the ISet collection object will not allow you to add duplicate news items.

The Author Mapping File and Class

The Author mapping file will be set up just like the News mapping file:

    1 <?xml version="1.0" encoding="utf-8" ?>

    2 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="News.Core" namespace="News.Core.Dto">

    3   <class name="News.Core.Dto.AuthorDto, News.Core" table="Author">

    4     <id column="AuthorId" name="AuthorId" type="long" unsaved-value="0">

    5       <generator class="native"></generator>

    6     </id>

    7     <property column="UserName" name="UserName" type="string" not-null="true"/>

    8     <property column="FirstName" name="FirstName" type="string" not-null="true"/>

    9     <property column="LastName" name="LastName" type="string" not-null="true"/>

   10     <property column="Password" name="Password" type="string" not-null="true"/>

   11     <property column="EmailAddress" name="EmailAddress" type="string" not-null="true"/>

   12     <property column="DateAdded" name ="DateAdded" type="DateTime" not-null="true" />

   13     <property column="DateUpdated" name ="DateUpdated" type="DateTime" not-null="true" />

   14     <property column="IsActive" name="IsActive" />

   15 

   16     <set name="NewsItems" table="News" generic="true" inverse="true">

   17       <key column="AuthorId" />

   18       <one-to-many class="News.Core.Dto.NewsItemDto, News.Core"/>

   19     </set>

   20   </class>

   21 </hibernate-mapping>

 

The first thing I need to is add the hibernate-mapping tag with xmlns namespace set so I can get the intellisense.  Next I add the Author class, specifying its namespace and assembly location, and just like the NewsItem class I start mapping the fields to the class properties.

As seen from the schema shown above, the Author table has a foreign key relationship in the News table, so I need to tell NHibernate about that relationship.  So to map the relationship, I have added a “set” tag.  The set tag tells NHibernate that the Author class has a collection of NewsItems and each of these news items are unique.  Now, if I wanted the Author class to have a collection of NewsItems that were not unique then I would use the bag tag, but in my case the set tag is what I want.

Here’s what’s going on:

·          The set attribute name is the child class that will be contained in the Author class.

·          The table attribute specifies the child table in the database that has the foreign key relationship.  In my case it is the News table.

·          Generic tells NHibernate that I want to use the ISet<T> collection  (Note:  This is a class that NHibernate provides is like the IList<T> class, but this class will not let you add a duplicate item to its collection.  I need to add a reference to the Iesi.Collections.dll assembly to use it.

·          Inverse tells NHibernate that I want the child class to control the relationship and not the parent.

·          The key column tells NHibernate what the foreign key field is in the child table.

·          And finally the one-to-many tag tells NHibernate what namespace and assembly the child class is in.

Woops!  Don't forget to make the mapping xml file an embedded resource.

Here is the class file.

    6     public class AuthorDto

    7     {

    8 

    9         public virtual long AuthorId { get; set; }

   10 

   11         public virtual string UserName { get; set; }

   12 

   13         public virtual string FirstName { get; set; }

   14 

   15         public virtual string LastName { get; set; }

   16 

   17         public virtual string Password { get; set; }

   18 

   19         public virtual string EmailAddress { get; set; }

   20 

   21         public virtual DateTime DateAdded { get; set;  }

   22 

   23         public virtual DateTime DateUpdated { get; set; }

   24 

   25         public virtual bool IsActive { get; set; }

   26 

   27         public virtual ISet<NewsItemDto> NewsItems { get; set; }

   28 

   29     }

 

Notice the ISet class?  Cool!

The News Mapping File and Class

The News class will slightly change.  Instead of holding the AuthorId field, the News class will be holding its parent Author class, so I will need to change the mapping file to reflect this also.

So here is the mapping file:

    1 <?xml version="1.0" encoding="utf-8" ?>

    2 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Audubon.Core" namespace="Audubon.Core.Dto">

    3   <class name="Audubon.Core.Dto.NewsItemDto, Audubon.Core" table="News">

    4     <id column="NewsId" name="NewsId" type="long" unsaved-value="0">

    5       <generator class="native"></generator>

    6     </id>

    7     <many-to-one name="Author" column="AuthorId" not-null="true" class="Audubon.Core.Dto.AuthorDto, Audubon.Core" />

    8     <property column="DateAdded" name="DateAdded" type="DateTime" not-null="true"/>

    9     <property column="DateUpdated" name="DateUpdated" type="DateTime" not-null="true"/>

   10     <property column="DatePublished" name ="DatePublished" type="DateTime" not-null="true" />

   11     <property column="Title" name="Title" type="string" not-null="true"/>

   12     <property column="ShortDescription" name="ShortDescription" type="string" not-null="false"/>

   13     <property column="Body" name="Body" type="string" not-null="true"/>

   14     <property column="IsFrontPage" name="IsFrontPage"/>

   15     <property column="IsPublished" name="IsPublished"/>

   16 

   17   </class>

   18 </hibernate-mapping>

 

Notice I have changed the AuthorId property tag to a many-to-one tag which specified the Author class.

Here is the NewsItem class with the modification for Author property:

    5     public class NewsItemDto

    6     {

    7         public virtual long NewsId { get; set; }

    8 

    9         public virtual AuthorDto Author { get; set; }

   10 

   11         public virtual DateTime DateAdded { get; set; }

   12 

   13         public virtual DateTime DatePublished { get; set; }

   14 

   15         public virtual DateTime DateUpdated { get; set; }

   16 

   17         public virtual string Title { get; set; }

   18 

   19         public virtual string ShortDescription { get; set; }

   20 

   21         public virtual string Body { get; set; }

   22 

   23         public virtual bool IsFrontPage { get; set; }

   24 

   25         public virtual bool IsPublished { get; set; }

   26     }

 

The Test

Now before I get into the test, at this point I should probably acquaint myself with the idea of lazy loading verses eager loading.  If you look at the two class above, the Author class has a collection of NewsItems classes and each of the NewsItem classes has a Author class which has a collection NewsItem classes, etc, etc, etc…

To get around this circular mapping, NHibernate uses the Proxy Pattern so that NewsItem class is not actually loaded until asked for in the code.  I can either get all the collection classes up front (eager loading) or I can get the class when I need them (lazy loading).  David Hayden wrote a nice explanation about the ramifications of either one using LightSpeed that you can read here.

I state that now, because I want to test that if I search for an author using a user id that I will get a collection of news items back for that author.  So since I am using lazy loading, I am not actually going to make to database calls for the news items until I inspect the collection of news items in the authors object I get back.

So here is the test:

  104         [TestMethod]

  105         public void NHibernateCanGetNewsItemsBySpecifiedUserId()

  106         {

  107             const string userId = "testuser";

  108             var target = new NHibernateDataProvider(session);

  109             var authors = target.GetAuthorsBy(userId);

  110 

  111             Assert.IsTrue(authors.Count > 0, "Authors count is not greater than 0");

  112             Assert.IsTrue(authors[0].NewsItems.Count >0, "Author's news items count is not greater than 0");

  113             Assert.IsFalse(authors.Count > 1, "Retrieved too many authors");

 

I am testing that my function GetAuthorsBy will return a collection of NewsItems.

Here is the function:

   42         public IList<AuthorDto> GetAuthorsBy(string userId)

   43         {

   44             return _session.CreateCriteria(typeof(AuthorDto))

   45                 .Add(Restrictions.Eq("UserName", userId))

   46                 .SetResultTransformer(new DistinctRootEntityResultTransformer())

   47                 .List<AuthorDto>();

   48 

   49         }

This function is using the NHibernate API to query the Author table by passing the userid.

Here is what is happening here:

·          CreateCritera starts off by asking what class I want to return.  I am telling to return a collection of Authors.

·          To add the Where Clause, I use the Add extension function and pass in the Restrictions.Eq function passing the property name and matching value.

·          By default, it is possible for me to get author “A” and then get author “B” and then again get author “A” in the collection, each with their own set of news items.  To avoid this I want to combine all duplicates so they only show up once.  Essentially this would be the equivalent to the DISTINCT statement in SQL.  I can do this using the SetResultTransformer extension function passing in the DistinctRootEntityResultTransformer.  This function will take the collection and merge the duplicates together (this done in memory not in the database).  Ayende gives some other examples and explanations here.

·          Finally the List extension tells NHibernate that I want a strongly types IList<AuthorDTO> class.

So when the function is called the following query is made to the database.

NHibernate: SELECT this_.AuthorId as AuthorId1_0_, this_.UserName as UserName1_0_, this_.FirstName as FirstName1_0_, this_.LastName as LastName1_0_, this_.Password as Password1_0_, this_.EmailAddress as EmailAdd6_1_0_, this_.DateAdded as DateAdded1_0_, this_.DateUpdated as DateUpda8_1_0_, this_.IsActive as IsActive1_0_ FROM Author this_ WHERE this_.UserName = @p0; @p0 = 'testuser'

Then when the test does an assert on the NewsItem count the following query is made.

NHibernate: SELECT newsitems0_.AuthorId as AuthorId1_, newsitems0_.NewsId as NewsId1_, newsitems0_.NewsId as NewsId0_0_, newsitems0_.AuthorId as AuthorId0_0_, newsitems0_.DateAdded as DateAdded0_0_, newsitems0_.DateUpdated as DateUpda4_0_0_, newsitems0_.DatePublished as DatePubl5_0_0_, newsitems0_.Title as Title0_0_, newsitems0_.ShortDescription as ShortDes7_0_0_, newsitems0_.Body as Body0_0_, newsitems0_.IsFrontPage as IsFrontP9_0_0_, newsitems0_.IsPublished as IsPubli10_0_0_ FROM News newsitems0_ WHERE newsitems0_.AuthorId=@p0; @p0 = '1'

In the next post I will look at testing the Service layer using Rhino Mocks and possibly throw in my first example of how I am going to use Unity.

 

 



Creating a Web Application Using MVC, Unity and NHibernate – Part 1

clock January 13, 2009 11:29 by author Steve

 

Introduction

 

I thought it would be useful to document what it would take to incorporate building a web application that is designed with the Microsoft MVC framework, that also incorporated using NHibernate as a O/R Mapper and uses Microsoft Unity as the Dependency Injection, IoC framework.  I must confess, I am not an expert of any of these tools, so I welcome feedback from the community.  The reason I am doing this to begin with, is there is not a whole a lot of documentation on of this “stuff” by themselves let alone all together, so I am hoping fill a little bit of that void.  If you think there are better approaches then what I am doing, feel free to provide feedback.   I am basically doing this for my own enrichment and if it is also helpful to the community, then—well—even better.

Since this going to have to be a series of posts, I will probably not cover every aspect of this application all at once, so if what you are looking for is not in this post, then be patient and maybe I will get to it in a later one.  As a matter of fact, since I am going to be adhering to a test first approach (red, green, refactor), I will probably not get to the MVC framework until several posts from now.  The first few posts will only be covering tests.

 

Setting up NHibernate

 

I have mentioned this before, but if you are new to NHibernate and don’t know how to get started, I highly recommend the Summer of NHibernate videos by Stephen Bohlen.  The download of NHibernate is located here.  Once downloaded, the first thing I need to do is put the NHibernate schema files in the Visual Studio schema folder (my folder is located here C:\Program Files\Microsoft Visual Studio 9.0\Xml\Schemas) so I can get intellisense on the configuration and mapping files. 

In general, for all the external libraries, it is useful to place them all in a folder location relative to, or just inside your solution so, for example, if you are using source control the other developer machines will pick up the references without any problems.  Thus, I am doing the same with this application, and will then be referencing the NHibernate.dll in all my relevant projects.  In my case, I am only going to have a Web, Core, and Test project so I will reference it for now in the Core and Test project.  I will probably need to reference in the web project once I set up Unity, but I will leave it out for now.

The next thing I will need to do is to create a NHibernate configuration file.  One of the cool concepts NHibernate follows is the Convention over Configuration paradigm.  That is, as long as I follow a certain convention, I will not need to configure certain aspects of NHibernate when setting it up.  So if I create a configuration file and name it hibernate.cfg.xml, then set is build action to copy to output folder, I will not need to tell NHibernate where the configuration file is.  Note:  I tried this in a Microsoft Team Test project and for some reason the test project would not copy that file to the output folder so I ended up having to configure the path anyway.

Here is the configuration file that is in the root directory of my test project.

    1 <?xml version="1.0" encoding="utf-8" ?>

    2 <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">

    3   <session-factory name="NHibernate.Test">

    4     <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>

    5     <property name="connection.connection_string">

    6       Data Source=(local);Initial Catalog=News;Persist Security Info=True;User ID=my_dev;Password=my_dev

    7     </property>

    8     <property name="adonet.batch_size">10</property>

    9     <property name="show_sql">true</property>

   10     <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>

   11     <property name="use_outer_join">true</property>

   12     <property name="command_timeout">444</property>

   13     <property name="query.substitutions">true 1, false 0, yes 'Y', no 'N'</property>

   14     <mapping assembly="News.Core"/>

   15   </session-factory>

   16 </hibernate-configuration>

 

Notice that in the root tag that since I place the NHibernate schema files in the Visual Studio schema folder I now have access to intellisense.  You can see the property setting definitions here, but here are the important nodes

·          The show_sql property is going to be useful when debugging so I can see the SQL statements.  I will turn this off in production because it is expensive.

·          The dialect is going to tell NHibernate to what specific database language and version it is going to translate the SQL to.

·          The mapping tells NHibernate where the mapping files and classes are located.

Once the configuration file is created, I then can call it from my code and create the ISessionFactory.  I will talk about my approach later in another post, but essentially because ISessionFactory is expensive to create and there also some threading concerns with creating it; I am going to create it differently in the test project than in the web project.  In both cases, I am going to implement an interface I created call ISessionFactoryManager.  This interface, as of now, will have one method called GetSessionFactory.  The code in my test project looks like this.

    1 using News.Core.Data;

    2 using NHibernate;

    3 using NHibernate.Cfg;

    4 

    5 namespace News.Web.Tests

    6 {

    7     internal class TestSessionFactoryManager : ISessionFactoryManager

    8     {

    9         public ISessionFactory GetSessionFactory()

   10         {

   11             string path = @"C:\Projects\News\Src\News.Web.Tests\hibernate.cfg.xml";

   12             var cfg = new Configuration();

   13             cfg.Configure(path);

   14             return cfg.BuildSessionFactory();

   15 

   16         }

   17     }

   18 }

 

 Note:  If I want, I can also add properties at run time.  For example, say my connection string is stored in a super secret place; I could get it and set the ISessionFactory with the following code.  It just has to be done before the BuildSessionFactory is called, because once called, it cannot be changed.

  15             cfg.Properties.Add("connection.connection_string",connectionString);

 

Once the BuildSessionFactory method is called, Nhibernate goes and retrieves the configuration file, and also the Mapping files (I will discuss later) and returns the session factory.  I now can open sessions to the database and do whatever database CRUD I need to do.

Mapping Tables to Classes

 For my example, I am going to have two tables with the following schema:


For this post, I am only going to worry about the News table.  Again, using convention over configuration, I have mapping file named NewsItemDto.hbm.xml so I do not have to tell NHibernate where it is.  I need to make sure this file is an embedded resource, so it can be referenced.  The content of the file looks like this:

    1 <?xml version="1.0" encoding="utf-8" ?>

    2 <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="News.Core" namespace="News.Core.Dto">

    3   <class name="News.Core.Dto.NewsItemDto, News.Core" table="News">

    4     <id column="NewsId" name="NewsId" type="long" unsaved-value="0">

    5       <generator class="native"></generator>

    6     </id>

    7     <property column="AuthorId" name="AuthorId" type="long" not-null="true"/>

    8     <property column="DateAdded" name="DateAdded" type="DateTime" not-null="true"/>

    9     <property column="DateUpdated" name="DateUpdated" type="DateTime" not-null="true"/>

   10     <property column="DatePublished" name ="DatePublished" type="DateTime" not-null="true" />

   11     <property column="Title" name="Title" type="string" not-null="true"/>

   12     <property column="ShortDescription" name="ShortDescription" type="string" not-null="false"/>

   13     <property column="Body" name="Body" type="string" not-null="true"/>

   14     <property column="IsFrontPage" name="IsFrontPage"/>

   15     <property column="IsPublished" name="IsPublished"/>

   16   </class>

   17 </hibernate-mapping>

 

Again, the root references the NHibernate mapping schema which will give me intellisense.  You can see all the property settings here.  In the class, I tell it the namespace and assembly name where the class is located.  The ID identifies the primary key of the table.  By setting the generator attribute to native, I am telling NHibernate that the field is an identity field and the value is created by the database.

Here is the code for the class:

    5     public class NewsItemDto

    6     {

    7         public virtual long NewsId { get; set; }

    8 

    9         public virtual long AuthorId { get; set; }

   10 

   11         public virtual DateTime DateAdded { get; set; }

   12 

   13         public virtual DateTime DatePublished { get; set; }

   14 

   15         public virtual DateTime DateUpdated { get; set; }

   16 

   17         public virtual string Title { get; set; }

   18 

   19         public virtual string ShortDescription { get; set; }

   20 

   21         public virtual string Body { get; set; }

   22 

   23         public virtual bool IsFrontPage { get; set; }

   24 

   25         public virtual bool IsPublished { get; set; }

   26     }

 

The properties are all virtual so NHibernate can utilize the proxy pattern for performance reasons.  This will come more into play when use the Authors table in following posts.

 

Creating the test

 

As a part of the buildup and teardown of my NHibernate tests, I will have each of my test create a session object that connects to the data base before the test starts and then close the session object once the test finishes.

    1 using News.Core.Data;

    2 using Microsoft.VisualStudio.TestTools.UnitTesting;

    3 using NHibernate;

    4 

    5 namespace News.Web.Tests

    6 {

    7     public class DatabaseBaseTest

    8     {

    9         private ISessionFactoryManager sessionFactoryManager = new TestSessionFactoryManager();

   10         protected ISession session;

   11 

   12 

   13 

   14         [TestInitialize]

   15         public void SetUp()

   16         {

   17             

   19             session = sessionFactoryManager.GetSessionFactory().OpenSession();

   20         }

   21 

   22         [TestCleanup]

   23         public void CleanUp()

   24         {

   25             session.Close();

   26             session = null;

   27         }

   28     }

   29 }

 

Now that I have Session I can create my first test.  This test will simply return 1 record from the NewsItem table by passing the NewsItemId parameter.

   78         [TestMethod()]

   79         public void GetNewsItemByItemIdShouldReturnMatchingTitle()

   80         {

   81             var target = new NHibernateDataProvider(session);

   82             const string expected = "test";

   83             const int itemId = 2;

   84             Assert.AreEqual(expected, target.GetNewsItemByItemId(itemId).Title);

   85         }

 

My database has a record which contains the Title value “test”.

 

The Repository

 

The data access code that gets the records looks like this:

   17         public NewsItemDto GetNewsItemByItemId(long newsItemId)

   18         {

   19             return _session.Get<NewsItemDto>(newsItemId);

   20 

   21         }

 

 

In the next post I will add the Authors table to the mix and some functionality retrieving those joined records.



Calendar

<<  September 2010  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar

Sign in