Thursday, December 11, 2014

Entity-ORM Hybrid

Sometimes you end up working on a project that shifts away from Entity Framework in favor of something else, ADO.NET, Linq to Sql, an available ORM, or maybe even a homegrown ORM.  That's what happened at one client I've worked with.  There were a few reasons to move away from EF, mostly based on misunderstandings, database design, and lack of knowledge of the product.  But there are still some things EF does better than some other methods.  Instead of writing a new stored procedure in SQL Server every time we need to update one field, we set out to use the features of EF to make that happen a little more easily.  After all, isn't it better when you can pass two variables to your repository and just wait for the true/false response?  That's right, it is better.

Here's the code:

   1:  public bool Save<T>(T domainModel, string idFieldName) where T : class
   2:          {
   3:              var type = typeof(T);
   4:              var idProperty = type.GetProperty(idFieldName);
   5:              var domainModelIdValue = (int)idProperty.GetValue(domainModel, null);
   6:   
   7:              var match =
   8:                  Context.Set<T>().Where(PropertyEquals<T, int>(idProperty, domainModelIdValue)).ToList();
   9:   
  10:              // if there's more than one record with a matching ID field (which shouldn't be possible as long as our field is specified correctly) we can't do this update
  11:              // also, if there's no match from the database on the ID field, we can't do this update
  12:              if (!match.Any() || match.Count() > 1)
  13:              {
  14:                  return false;
  15:              }
  16:   
  17:              var firstMatch = match.First();
  18:   
  19:              // set all properties from the domain model passed to the match found in the database
  20:              Context.Entry(firstMatch).CurrentValues.SetValues(domainModel);
  21:   
  22:              var numberOfObjectsWrittenToUnderlyingDatabase = Context.SaveChanges();
  23:   
  24:              return numberOfObjectsWrittenToUnderlyingDatabase == 1;
  25:          }
  26:   
  27:          public Expression<Func<TItem, bool>> PropertyEquals<TItem, TValue>(PropertyInfo property, TValue value)
  28:          {
  29:              var param = Expression.Parameter(typeof(TItem));
  30:              var expressionProperty = Expression.Property(param, property);
  31:   
  32:              BinaryExpression body;
  33:              if (Nullable.GetUnderlyingType(expressionProperty.Type) != null)
  34:              {
  35:                  var comparisonValue = Expression.Convert(Expression.Constant(value), typeof(int?));
  36:                  body = Expression.Equal(expressionProperty, comparisonValue);
  37:              }
  38:              else
  39:              {
  40:                  body = Expression.Equal(Expression.Property(param, property), Expression.Constant(value));
  41:              }
  42:   
  43:              return Expression.Lambda<Func<TItem, bool>>(body, param);
  44:          }

Tuesday, December 2, 2014

Angular ng-include

If you need to bring one HTML file into another using Angular, you may want to take advantage of the ng-include directive (documentation can be found here).  Using ng-include will bring in the specified HTML file.

<div ng-include="'/Pages/SomeApp/Ordering.html'">

Be careful, though!  I ran into a problem with this directive that was driving me crazy.  I had used ng-include in a file that also had an ng-include in it and it caused me no small headache.  Others have done the nested ng-include so it may have just been my specific usage that was causing problems, but it's worth noting.

In case you're seeing something similar, I was forced to use IE 8 (you can peruse my hatred of that browser in other posts) and whenever the ng-hide class was applied, the entire screen went blank.  The DOM was technically still there, but you couldn't see anything.  Good times.  Or not.

Plain HTML as a Partial View

Sometimes you just need to include a plain HTML file in another MVC view.  It's easy enough.  Just use the code below and you should be all set.

@Html.Raw(File.ReadAllText(Server.MapPath("~/Pages/SomeApp/Ordering.html")))

Friday, November 7, 2014

Scope Objects in the Console

When you need to quickly print a scope value in the console (I use Chrome), you can use this helpful little guy:

angular.element("#elementId").scope()

Just a little bit of code that can help immensely.

Friday, October 10, 2014

Stayin' Alive

It's been a while since I posted.  I'm not sorry.  Life is busy.  You'll just have to learn to deal with missing me.  That's how our love works.

I recently had to figure out how to keep my .NET application "alive" or "awake" between requests.  This particular site belongs to a small business that is just getting started.  Since they're not sure how big their site might get we decided to stay small and use shared hosting from GoDaddy.  One of the problems they were encountering was that the site was always so "slow".  I couldn't figure out what they were talking about for quite some time until I finally hit the page early one morning, before anyone else had hit it for the day.  It was slow.  Obnoxiously slow.

IIS was recycling the app pools when no one visited the page for a period of time.  What I needed was a solution to make that stop happening.  I found a clever little solution that works for us, but has some obvious pitfalls.  H/t to Omar Al Zabir at Codeproject for this one.  If you actually clicked that link and read the original solution you may have noticed that it's quite old.  But who cares?  It works.

Basically, you create a cache item with a callback.  When the cache item expires and the callback fires, the callback hits your site.  I modified the solution a little bit to do what I needed.  I have a separate service from my website so I wanted to keep both of them alive.  Easy.  Check it out.

This is from the global.asax.cs from the web project:


That's pretty much the whole shebang right there.  Actually, that's not "pretty much" it.  That's it.  There are obviously some web.config values to add, but I think you can figure that out.

Tuesday, September 23, 2014

Angular JS ajaxComplete

I recently came across a problem where our ajaxComplete function wasn't being executed from jQuery after we started using Angular.  As it turns out (it was a bit of a "duh" moment) the issue was that when using Angular we were no longer using the jQuery ajax calls.  So the jQuery ajaxComplete function was never fired because no jQuery ajax calls were ever made.

That set me on a path of trying to figure out how to mimic the ajaxComplete behavior with Angular and this is what I came up with.  I haven't fully tested it, but wanted to put it up here before I forget so I can have a better starting point next time this comes up.

After the application has been created, configure the $httpProvider to have an intercept:

angularApp.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push(function ($q) {
        return {
            response: function (response) {
                return response;
            }
        };
    });
}
]);

This particular implementation won't do anything but act as a pass through, but it can be modified however necessary to meet your needs.

Monday, August 11, 2014

Getting Distinct from a List

Sometimes you have a list of complex objects that you need to pare down to be a list of distinct complex objects.  LINQ offers a way to do that, but unless you've done it before it's not immediately obvious as to what you need to do.  There are two ways to do it, and they're actually pretty easy to implement.

If the complex object is your own creation, just implement IEquatable where T is the type of the object.  Something like this:



Once you've implemented IEquatable on your class, you just have to invoke the .Distinct() call on your list.  Here you go:



Here are the results of the IEquatable approach:


If you find yourself in a situation where the complex object can't be extended to implement IEquatable, there's a solution for that, too.  You'll create an additional class that implements IEqualityComparer and then specify that when you invoke the .Distinct() call on your list.







Here are the results of using the IEqualityComparer approach:

Monday, August 4, 2014

Going Loopy for Performance (C#)

I may have written about this before, and if so, I apologize.  Wait, no I don't.  I couldn't find it and this blog is for me anyway.  I retract my apology.  Anyway, if you've ever wondered whether your loop is as fast as it can be, I have some answers for you.

I read one time that a for loop is faster than a foreach loop in C#.  I can buy that, I suppose.  But in the same article it said that iterating backward through a for loop is faster than iterating forward and I had a hard time getting on board with that.  So I wrote some tests.  That author was right.

I wanted to test a variety of options, so I did.  That's how I roll.  I ran each test over 100,000,000 iterations.

The first test was a regular for loop:

...and the results:


Next up I did the same thing but without previously specifying the size of the loop (I use .Count as the upper limit of the loop):

...and the results:


You can see that of the two options, it is slightly faster to set the upper limit in a variable.  "Slightly" here meaning 11 milliseconds over 100,000,000 iterations, or .00000011 milliseconds per iteration.

Moving on.  Next we have the reason for my testing in the first place: the reverse for loop:

...and the results:


Whoa!  That's a bit of an improvement.  37 milliseconds over 100,000,000 iterations (compared to our previous best time), or .00000037 milliseconds per iteration.

This time the reverse loop without a variable:

...and the results:


Based on the earlier results of the forward for loop, this makes sense.  Next was a foreach loop over a list:

...and the results:


Wow.  That's a significant degradation.  Our previous worst time (a forward for loop with a variable as our upper bound) was 240 milliseconds.  The foreach on a list (which is, in my opinion, the easiest loop to write) takes nearly twice as long to run.

Last up is a foreach loop on an array instead of a list:

...and the results:


The overall results certainly point to a reverse for loop with a variable as the lower bound is the fastest we can iterate through an array.

BUT WAIT, THERE'S MORE!  I found this last bit while I was writing this up.  It's an alternative way to do a decrementing for loop that's actually slightly faster than anything else up there.

...and the results:


I learned a couple of lessons on this one.  First, don't always go with the easiest thing to do because it may not be the best thing to do.  Second, minor functions can have major performance implications.  In this example, I just incremented a variable during the iteration, but in a real world scenario I may do anything from build a complex object to make a service call.  This basic example showed us a difference of 279 milliseconds over 100,000,000 iterations.  That is a really small number per iteration, but keep in mind that the only thing we were doing was incrementing a counter.  If we had been doing any real work that would have been a major performance hit.

Sunday, August 3, 2014

Tracing with Unity

One of the most consistent issues that comes up with software is the need to improve performance.  Even if your application is really fast 99% of the time, someone will want you to improve it at some point.  That's just a fact of life.  The problem is that it's really hard to improve the overall performance of your application if you don't know where the performance is lacking.

I once had a boss who, upon learning that the performance of the new application was not to his standards, demanded that we fix it immediately.  When we pressed him for what was slow he answered "all of it" and "just the whole thing".  We said "let us put some logging in place so we can identify which parts are too slow and then we'll fix it", which was met with "no, just fix it now".

Ever since that incident, I've made it a point to build in a tracing feature that can be switched on or off with a small change to the configuration file.  Recently (as in, two days ago) I found that the old way of tracing wasn't working for me anymore and I had to figure out how to do it all over again.  Here is the fruit of my labor.

First, create the TraceCallHandler class:


Here's some more detail on that one:



The Invoke method is the one that actually interrupts the call.  You can see that all we're doing here is building the arguments list, getting the name of the method being called (including the type in which it's declared in case you have the same method name in multiple places), and starting a stopwatch around the actual method call.  We let the method do its thing, then log the whole shebang on a new thread.



I struggled with this one for a while, but ultimately settled on this.  Basically, I'm trying to see what parameters were used to call the method being executed.  This is helpful when the parameters are primitive types, but if a complex object is passed, it doesn't tell me a whole lot.



Basically at this point we're just passing the values we've collected into a stored procedure so we can review the data when we're ready.  And on that note, here's the stored procedure:



Aaaaaaand the table that stored procedure writes to:



To use the trace attribute all you have to do is add it as a decorator to the interface that has the methods you want to trace.  In this case we're going to trace all methods on the IAboutManager class:



But that'll only work if we configure tracing back in our Unity container.  Like this:



And then we have to configure the actual trace on the IAboutManager interface, like this:



And that's it.  That little bit of code (OK, it's a lot of code, but it did all fit in a single post) will enable tracing with two values from the web.config set to true.  Oh, I forgot that part.  Here you go:


Monday, June 23, 2014

More Angular .NET Routing

This is a quickie to expand on a couple of things I mentioned here.

In that other post I mentioned that you'll need a controller for each page if you want your users to be able to navigate to them directly. That's true, but you don't need a separate view for each one.  What I do instead is redirect every action method for every controller to the same view (~/Views/Home/Index).  That way the Angular routes can take over and everything will work the way you want without a bunch of clutter in your solution.












The next thing is a bit of a correction, sort of.  In the last post I said you should replace @RenderBody() with something else.  Well, I had to create my application anew and that little bit really caused me some trouble.  It now appears you don't want to remove @RenderBody() at all because that will cause some issues in your site.  I'm not issuing a formal change until I can get back to that original application (on my other computer) and try to figure out why it works there and not here.  In the meantime, you can do this instead of following step 22.






There's bound to be more little things I find so I'll try to keep things updated as much as possible.

Thursday, June 19, 2014

IE(h)8

So you just settled in to your new job and you got a support ticket that says "the textbox is jumpy".  Feeling sure of yourself, you go straight to the control in question and immediately start trying to reproduce the error.  Right away you notice the control is not a "textbox", but a "textarea" and you store that little nugget for later.  You open Chrome and start hammering away on the textarea trying to make it "jump" to no avail.  Being someone who is particularly thorough, you call the tester and ask what they were doing when they saw the bug.  After a bit of back and forth the tester finally admits he was testing in IE.  Ah, maybe that's the problem.

So you open IE on your machine (which was built after Castro retired (pay attention, that's important)) and try to reproduce the bug there.  Still with no way to reproduce the issue, you pay the tester a visit.  You immediately recognize that one of your worst fears has come true.  The tester is using an old version of Internet Explorer.  Specifically, he's using IE8.

OK, fast forward a few hours.  You've pulled out 30% of your hair, involved two other developers, one business analyst, and a partridge in a pear tree.  The partridge isn't particularly helpful, but the pears are delicious.  You still can't find anything.  You finally consult the Mighty Internet and as you type "IE8 textarea" Google (because you switched back to Chrome, because of course you did) helpfully auto populates the most commonly searched terms with... "scroll bug".

The first result of that search takes you here, where the very helpful author explains that you're not crazy and neither is your tester.  Microsoft just (surprise) released something with a really-annoying-but-not-commonly-encountered-bug in it.  The fix is simple and everyone is happy.

Except your hair follicles.  They're super pissed at you.

Wednesday, June 18, 2014

Angular.NET Routing

Well, hello again.  In this post I'm going to explain how to set up routing with Angular routes to implement a Single Page Application (SPA).  A SPA may not be best for your needs, but I believe it's helpful to know how to do something (or at least that it's possible) before you need to actually do it.

First things first, if you haven't read the first part of this post, you may want to do that before you continue.  Even if you're already familiar with AngularJS and .NET, I created a sample application in that post that I'll be expanding in this post.

One really important note before we jump into this: if you want people to be able to hit each page directly in a SPA, you'll still need to create .NET controllers.  For example, we're going to route everyone who hits http://localhost:47125 to Pages/Home.html, but if we don't have a .NET controller for /Home/Index the user will get a 404 error.  I don't cover that part in this guide because it's late and I want to go read my book before I go to bed.  Don't laugh... seriously, I can still hear you.  What, a guy can't read before bed?

  1. In the last post, we only added AngularJS Core from NuGet.  This time we're going to add the full blown Angular suite.  Follow steps 4 - 7 in the last post, but when you get to step 8, choose "Angular JS" instead of "AngularJS Core"
    1. When you do this, you should get a couple of warnings that the file already exists; that's OK, go ahead and replace the current file with the new one
  2. Open the file you created in step 16 of the last post, "angular-start.js"
  3. Inside the brackets add "'ngRoute'" (with the single quotes around it, but not the double quotes)
  4. Beneath that, add what you see below
  5. There is something very important to note here: I'm not routing to "Views/Home.cshtml" or "Home[Controller]/Index".  We're going to create a Pages directory and use that, otherwise (in my experience at least) your .NET routes will interfere with your Angular routes
  6. Right-click "AngularTutorial.Presentation.Web" and choose "Add > New Folder" from the popup menu
  7. Name the folder "Pages"
  8. Right-click the new "Pages" folder and choose "Add > New Item..." from the popup menu
  9. Scroll down the list of items you can add and click "HTML Page"
  10. Change the name to "Home.html"
  11. Click the "Add" button
  12. Repeat steps 8 - 11 of this tutorial twice, once for "Contact.html" and once for "About.html"
  13. Follow steps 28 - 33 in the first tutorial three times, creating "contactController.js", "aboutController.js", and "homeController.js"
  14. Copy/paste the contents of "angularController.js" into each of the three files you created in step 13
  15. Change the name of the controller in each of the files you created in step 13 to match the name of the file
    1. For example, change "angularController" to "homeController" in the homeController.js file
  16. Change the message to something unique for each controller
  17. Expand "AngularTutorial.Presentation.Web > App_Start"
  18. Open "BundleConfig.cs"
  19. In the bundle you created in step 37 of the first post, add the three new controllers you created in step 13 of this post
  20. In the same bundle, add the "angular-route.js" file that should have been included in your project in step 1
  21. Expand "AngularTutorial.Presentation.Web > Views > Shared" and open "_Layout.cshtml"
  22. Replace @RenderBody() with this
  23. In the same file, locate the ul with id "menu" and remove the 3 default tags
  24. Insert these tags where you just removed those others
  25. Notice the path for each of them corresponds to the routes you created in step 4
  26. Follow steps 40 - 43 of the first post

Monday, June 16, 2014

Angular.NET

OK, so the title is a bit misleading.  There is no such thing as Angular.NET (as far as I know), but that doesn't mean we can't mash up AngularJS with ASP.NET to make some really neat applications.  I had a bit of trouble getting started and I couldn't find a comprehensive tutorial anywhere so I put one together.  I even used pictures!

This tutorial is intended to walk you through every tiny step so it may seem tedious at times.  Just go with it.  Or scroll past the parts you already know and get to the good stuff.  I just wanted to be really thorough so next time I start something from scratch I don't have to wonder at all about what I did last time to make it work.

There are a couple of items to note before we jump in.  First (and possibly most importantly), all file names are arbitrary.  If I say "Create a file called angular-start.js" and you want to call it "friggafrompton.js", that's fine.  But later when I reference "angular-start.js", you'll have to remember you named it "friggafrompton.js" and make the appropriate adjustments.  Secondly, the reason I'm starting with a blank solution is for future enhancements to this application.  If you want to just create a new project, that's fine, but again, you're responsible for remembering you did that later.  Next, when you see a word inside brackets, it references a key on the keyboard. So [Enter] means the Enter key on your keyboard.  When you see something in quotes and I tell you to type it somewhere, don't type the quotes.


  1. Open Visual Studio (I use VS 2012)
  2. Create a new Blank Solution named "AngularTutorial"
  3. Add a project named "AngularTutorial.Presentation.Web" to the blank solution
  4. Expand "AngularTutorial.Presentation.Web" and right-click "References"
  5. Click "Manage NuGet Packages"
  6. In the left windowpane, select "nuget.org" or "All"
  7. In the upper right-hand corner of the window, type "AngularJS" and press [Enter]
  8. For this tutorial, only install AngularJS Core
  9. Expand "AngularTutorial.Presentation.Web > Views > Shared"
  10. Open _Layout.cshtml
  11. Edit the html tag in _Layout.cshtml to include "ng-app='angularApp'"
  12. Expand "AngularTutorial.Presentation.Web"
  13. Right-click "Scripts"
  14. Choose "Add > New Item..."
  15. Scroll down the list of items you can add and click "Javascript File"
  16. Change the name to "angular-start.js"
  17. Click the "Add" button
  18. Add the following line to the top of the blank file ("angular-start.js")
  19. Expand "AngularTutorial.Presentation.Web"
  20. Right-click "Controllers"
  21. Choose "Add > Controller..."
  22. Name the Controller "AngularController"
  23. Click the "Add" button
  24. In the open "AngularController.cs" file, right-click "View()" and choose "Add View..."
  25. Check the box marked "Create as a partial view"
  26. Click the "Add" button
  27. Add the following markup to the top of the blank file ("Index.cshtml")
  28. Expand "AngularTutorial.Presentation.Web"
  29. Right-click "Scripts"
  30. Choose "Add > New Item..."
  31. Scroll down the list of items you can add and click "Javascript File"
  32. Change the name to "angularController.js"
  33. Click the "Add" button
  34. Add the following line to the top of the blank file ("angularController.js")
  35. Expand "AngularTutorial.Presentation.Web > App_Start"
  36. Open "BundleConfig.cs"
  37. Somewhere in the RegisterBundles method, add the following code
  38. Go back to "_Layout.cshtml"
  39. After the jQuery bundle is added, add the new angular bundle
  40. Build the solution
  41. Start without debugging
  42. Navigate to /Angular
    1. In my case it was http://localhost:47125/Angular
  43. Witness the fruits of your labor