Wednesday, February 29, 2012

finally

try {

}

catch {

}

finally {

}

 
 

Remember the finally. This is a good place to close that SqlConnection you opened.

classes, delegates, and interfaces are reference types

http://msdn.microsoft.com/en-us/library/490f96s2(v=vs.80).aspx

I wish I still had my "Udi Dahan" notes.

In 2008 I took an SOA training taught by Udi Dahan. I wish I could find my notes. I think they are sitting on a server Headspring has probably gotten rid of. :(

 
 

Udi's NServiceBus wraps MSMQ (Microsoft Message Queuing) and takes the pain out of using it. I say that having never used NServiceBus myself.

 
 

Here I found a link to here listing the 8 fallacies of distributed computing:

  1. The network is reliable.
  2. Latency is zero.
  3. Bandwidth is infinite.
  4. The network is secure.
  5. Topology doesn't change.
  6. There is one administrator.
  7. Transport cost is zero.
  8. The network is homogeneous.

 
 

This goes into the five types of coupling:

  1. Afferent (if X depends on Y, Y is afferently coupled to X)
  2. Efferent (if X depends on Y, X is efferently coupled to Y)
  3. Platform
  4. Temporal
  5. Spatial

searching folders in Windows 7

This touches on searching folders in Windows 7 and in particular suggests that you go to:

Organize > Folder and search options > Search

 
 

...from the Orgainize button on the file view for a given folder to tweak search settings.

Tuesday, February 28, 2012

more of mutable, immutable, stack, and heap

Again: Value types are immutable (they cannot change) while reference types are mutable, and value types go on the stack and reference types go on the heap.

http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap asserts:

  1. THE STACK is the memory set aside as scratch space for a thread of execution. When a function is called, a block is reserved on the top of the stack for local variables and some bookkeeping data.
  2. THE HEAP is memory set aside for dynamic allocation. Unlike the stack, there's no enforced pattern to the allocation and deallocation of blocks from the heap; you can allocate a block at any time and free it at any time.

 
 

http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx goes into boxing and unboxing which has to do with converting a value type to an object or, in the case of unboxing, an object back to a value type. An example of boxing:

int i = 123;

object o = i;

 
 

...of unboxing:

o = 123;

i = (int)o;

 
 

This image shows how another piece of memory is allocated in the boxing process. Hence, there are some performance issues with boxing as a value type on the stack gets copied to the heap as it is boxed. (That said, you are very likely better off worrying about how to optimize database integration in the name of reducing lag instead of having angst over boxing and unboxing.)


 
 

Value objects are not always just simple types:

http://tom-jaeschke.blogspot.com/2011/12/entities-have-both-state-and-lifecycle.html has my notes from when I saw Paul Rayner speak on DDD. He suggested that Eric Evans suggests that objects which are not entities (and thus do not have a lifecycle) should be (if not DTOs) value types. Examples given of value domain objects that one might speak about in ubiquitous language were:

  1. Warranty (no lifecycle, once it's set its dates and conditions are not going to change)
  2. Terms & Conditions (same thing)

Saturday, February 25, 2012

How to deal with phone number hyperlinks???

I found this posting on getting rid of phone number hyperlinks. It suggests turning them off like so:

<meta name="format-detection" content="telephone=no">

 
 

...and on like so:

<a href="tel:1-408-555-5555">1-408-555-5555</a>

 
 

I have yet to try it.

Wednesday, February 22, 2012

phone number hyperlinks irritate me

http://www.petefreitag.com/item/751.cfm touches on getting rid of the ones imposed by Skype.

hexagons!

I figured out how to make an endless grid of hexagons spiral outwards from a central point.

see: http://www.tomjaeschke.com/blog/code.zip

web safe fonts

http://www.w3schools.com/cssref/css_websafe_fonts.asp is a good cheatsheet.

when ReSharper hot keys stop working...

If ReSharper isn't working, go to ReSharper > Options... > Visual Studio Integration and make appropriate changes there. Press the "Apply Scheme" changes when finished. In the worst case scenario go to www.jetbrains.com/resharper/ to reinstall ReSharper.

Tuesday, February 21, 2012

MSSQL Triggers and @@IDENTITY and SCOPE_IDENTITY()

I took the SQL here and added this to it:

CREATE TRIGGER dbo.AddressTrigger

   ON dbo.Address

AFTER INSERT

AS

INSERT INTO Person (PersonId, Name, AddressId)

VALUES (NEWID(),'I need a name','1ba51989-84fb-4a61-8c35-9e6a007bc0fb')

 
 

In doing so I created a trigger that will fire whenever a row is inserted into the Address table. The trigger will make a new row in the Person table. I wanted the process to assign the Person the Address of the Address just created, but I find in hard to know what the uniqueidentifier most recently used is. :(

I found this stuff in Googling to figure out the above:

  1. http://www.youtube.com/watch?v=5zyQIt-8NRQ
  2. http://www.kodyaz.com/articles/sql-trigger-example-in-sql-server-2008.aspx
  3. http://stackoverflow.com/questions/42648/best-way-to-get-identity-of-inserted-row
  4. http://www.kodyaz.com/articles/sql-trigger-example-in-sql-server-2008.aspx
  5. http://vyaskn.tripod.com/retrieve_guid_value_like_identity.htm

Some of the above touches on @@IDENTITY and SCOPE_IDENTITY() would have been handy for solving the problem above if I were using ints for ids instead of guids.

It's OK to feel conflicted.


It's very often best to just admit that you're not 100% sure you want what you think you want. If you have a voice inside saying "I think I want that glowy grabme, but I wish I also had a way to change my mind once I put my hands on it" such a thought is not only normal, but healthy. The nature of the Agile process allows one to push big commitments as far down the pipe as possible to allow all parties involved to have some time to chew on whether or not they really want to do a specific thing. In building a jigsaw puzzle, when one picks up a given puzzle piece, rotates it in hand, and chews on if he/she really wants to use it, typically one has the benefit of surveying how all of the other pieces have come together to date and thus the current shape of things effects the decision at hand more than any other factor might. It is good to have all of the information possible to make an informed decision and it is good to a make decisions that will allow you to make such informed decisions. Running a project with an Agile process will allow one to make informed decisions a lot more so than a Waterfall process.

We are just now starting an Agile process. We are fighting our way through some of the pain points, such as not baking enough story points. We are doing better. We are in a second leg of our project.

In the first leg: A liaison (middleman) between our team and the product owners had written a huge functional spec around what he felt the users wanted and we were trying to jam hunks of the Word document into stories and we were... pretending to have an Agile process around the pseudostories.

There is not an Agile process without stakeholder feedback however. We were chipping away at the functional spec in a Waterfall manner.

Eventually the middleman's management style caught up to him and he felt the need to quit. In his absence we started doing things the right way. We are now interfacing directly with the customers that we had been "protected from."

That said, plenty of time has been wasted in going down tangents:

  • We were to build an autonaming feature for a particular object. We spent time planning for it and debating it. It turns out that the stakeholders didn't want it at all. It was an imposition by the middleman.
  • We abstracted the name for another object out to a separate database table in the name of... well, I don't understand why we did it. I think it had to do with making sure that no two objects have an identical name. It doesn't really make sense. The middleman wanted it. It was in the functional spec.

I've now seen firsthand, on the same project, the difference between Waterfall and Agile. I wanted to share my tale. The lesson: Don't try to have all of the answers upfront.

It's OK to feel conflicted.

Closures

My previous understand of Closures is bad.

Derek Greer's is much better.

Some of his code:

var createGreeting = function(greeting) {

   return function (name) {

      document.write(greeting + ', ' + name + '.');

   };

};

   

helloGreeting = createGreeting("Hello");

howdyGreeting = createGreeting("Howdy");


helloGreeting("John");

helloGreeting("Sally");

howdyGreeting("John");

howdyGreeting("Sally");


// Hello, John.

// Hello, Sally.

// Howdy, John.

// Howdy, Sally

Monday, February 20, 2012

hand in settings for options in "newing up" a jasmine-jquery widget

$(document).ready(function () {

   var target = $('#portletwrapper');

   var widget = target.Portlet({

      foo: "bar",

      baz: "qux"

   });

});

wire a click event to a child element within a jasmine-jquery widget

setup: function (defaultStateIsOpen) {

   self.options.stateIsOpen = defaultStateIsOpen;

   self.options.container = self.element;

   self.definePortletHeader(self.options.container.children(":nth-child(1)"));

   self.definePortletContent(self.options.container.children(":nth-child(2)"));

   self.alterAppearanceBasedOnOpenState();

   self.options.portletHeader.click(function () {

      self.toggle();

   });

   self.reveal();

},

using options with jasmine-jquery widgets

setup: function (defaultStateIsOpen) {

   var self = this;

   self.options.stateIsOpen = defaultStateIsOpen;

   self.options.container = self.element;

   self.definePortletHeader(self.options.container.children(":nth-child(1)"));

   self.definePortletContent(self.options.container.children(":nth-child(2)"));

   self.alterAppearanceBasedOnOpenState();

   self.reveal();

},

alterAppearanceBasedOnOpenState: function () {

   var self = this;

   if (self.options.stateIsOpen) {

      self.options.portletHeader.children("span").removeClass('ui-icon-plusthick');

      self.options.portletHeader.children("span").addClass('ui-icon-minusthick');

      self.options.portletContent.removeClass('hide');

   } else {

      self.options.portletHeader.children("span").addClass('ui-icon-plusthick');

      self.options.portletHeader.children("span").removeClass('ui-icon-minusthick');

      self.options.portletContent.addClass('hide');

   }

},

options: {

   stateIsOpen: false, //REQUIRED

   stateIsPersisted: false

}

a better posting on method calling with jasmine-jquery

This post on jasmine-jquery method calling was a little confusing for me when I tried to use it for my own reference. So, instead see the following:

var target = $('#portletwrapper');

var widget = target.Portlet();

var act = widget.Portlet('setup', false);

 
 

That calls this method:

setup: function (defaultStateIsOpen) {

   var self = this;

   
more code here...

},

Sunday, February 19, 2012

test to see if a class exists in a jasmine-jquery widget

https://github.com/velesin/jasmine-jquery offers that one may use this trick to see if an element has a class or not:

expect($('#foo')).not.toHaveClass('hide');

latch onto the first two divs within a div in a jasmine-jquery widget using jQUery's nth-child

self.options.container = container;

self.definePortletHeader(self.options.container.children(":nth-child(1)"));

self.definePortletContent(self.options.container.children(":nth-child(2)"));

noolog.com

...will allow you to cast a url to sort of a barcode image and Google Googles will allow you to get it back into url format.

Friday, February 17, 2012

What is long polling?

I fished the following out of here:

In web programming, it is an emulation of pushing data, implemented by repeated polling with delayed response.For instance, data may be "pushed" to an HTTP client by using a long-standing HTTP request with protracted response, hence the term "long poll". A true push data model is not otherwise available to the client because it cannot receive incoming HTTP connections.

Thursday, February 16, 2012

at startup

Try to get around the problem in which an inappropriate project defaults to be the starup project in a solution with:

Tools > Options... > Environment > Startup > At startup:

FOUC

...stands for flash of unstyled content

Wednesday, February 15, 2012

http://pastie.org/

...seems cool

jQuery width

outerWidth(true) is wider than outerWidth is wider than innerWidth is wider than width

Widths are gagued without regard to whitespace. One has to use the &nbsp; hack to account for whitespace.

Craig suggests...

If you desire a new build to run, you don't need change code to make this happen. Go to the "Team Explorer" and select builds and "Queue Build".

Chosen JavaScript plugin

http://harvesthq.github.com/chosen/

default in C#

default(Foo) gives the default configuration for the type of Foo. I don't understand it yet.

http://weblogs.asp.net/avnerk/archive/2006/05/21/Non_2D00_generic-default-values-in-C_23003F00_-Why-not_3F002100_.aspx

Joel suggests...

Serializing using a stream should side step any default string size limitations. You can do it like this:

var serializer = new Newtonsoft.Json.JsonSerializer();

var writer = new StringWriter();

serializer.Serialize(writer, obj);

writer.Flush();

string serializedObject = writer.GetStringBuilder().ToString();

Tuesday, February 14, 2012

how to find something in an .edmx without scrolling around in hopes of stumbling upon it

  1. double-clicking on the .edmx in the Solution Explorer should open the .edmx in the Model Browser
  2. expand the Entity Types folder
  3. right-click on the desired entity and select "Show in Designer"

call stack

Open call stack (while debugging) from: Debug > Windows > Call Stack

Use it to see what method is invoking the method which is failing.

Green Arrow

When one sets a breakpoint in Visual Studio and one reaches the breakpoint in executing code, one will notice a green arrow within the breakpoint. The arrow may be dragged upwards to lines of code above the breakpoint and from the green arrow one may step back through code previously run again.

Friday, February 10, 2012

I monkey with Func

I wrote this class:

using System;

namespace FuncExperiment.Models

{

   public class SomethingFunky

   {

      private Func<string> _whatever;

      private Func<Int16> _flapdoodle;

      

      public SomethingFunky()

      {

         _whatever = () => "just getting started";

         _flapdoodle = () => 7;

      }

      

      public string SprayFunc()

      {

         return _whatever();

      }

      

      public void PushInStringValue(string value)

      {

         _whatever = () => value;

      }

      

      public void PushInIntegerValue(Int16 digit)

      {

         _flapdoodle = () => digit;

      }

      

      public void MakeStringFromInteger()

      {

         _whatever = () => TryToGiveGermanNameForSingleDigit(_flapdoodle());

      }

      

      private static string TryToGiveGermanNameForSingleDigit(Int16 digit)

      {

         
//follow this link to see the guts of this method

 
 

...and got it under test like so:

using FuncExperiment.Models;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FuncExperiment.Tests

{

   [TestClass]

   public class TestsForSomethingFunky

   {

      [TestMethod]

      public void test_constructor()

      {

         SomethingFunky skunk = new SomethingFunky();

         Assert.AreEqual(skunk.SprayFunc(), "just getting started");

      }

      

      [TestMethod]

      public void test_changing_string()

      {

         SomethingFunky skunk = new SomethingFunky();

         skunk.PushInStringValue("this is new");

         Assert.AreEqual(skunk.SprayFunc(), "this is new");

      }

      

      [TestMethod]

      public void test_goofy_German_translation()

      {

         SomethingFunky skunk = new SomethingFunky();

         skunk.PushInIntegerValue(2);

         skunk.MakeStringFromInteger();

         Assert.AreEqual(skunk.SprayFunc(), "zwei");

      }

      

      [TestMethod]

      public void must_explicity_call_integer_to_string_translation()

      {

         SomethingFunky skunk = new SomethingFunky();

         skunk.PushInIntegerValue(2);

         Assert.AreNotEqual(skunk.SprayFunc(), "zwei");

      }

   }

}

Thursday, February 9, 2012

I'm not going to change my last blog posting (don't have time) but I realize I've botched the name of the class in it.

Should not have "Summation" in the name. This was appropriate only before I started refactoring. :P

testing private methods in C# with reflection

I wrote this class...

namespace PrivateMethodTesting.Models

{

   public class SummationScienceExperiment

   {

      public int DependentVariable { get; private set; }

      public int IndependentVariable { get; private set; }

      public double? DivisionCalculation { get; private set; }

      

      public SummationScienceExperiment(int ofStone, int ofClay)

      {

         DependentVariable = ofStone;

         IndependentVariable = ofClay;

         DivisionCalculation = craftDecimal(ofStone, ofClay);

      }

      

      public void Update(int ofClay)

      {

         IndependentVariable = ofClay;

         DivisionCalculation = craftDecimal(DependentVariable, ofClay);

      }

      

      private double? craftDecimal(int ofStone, int ofClay)

      {

         if (ofClay == 0) return null;

         return (double)ofStone/(double)ofClay;

      }

   }

}

 
 

...and then I wrote the following four tests around it. The last test uses reflection to test the private method.

using System;

using System.Reflection;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using PrivateMethodTesting.Models;

namespace PrivateMethodTesting.Tests

{

   [TestClass]

   public class SummationScienceExperimentTests

   {

      [TestMethod]

      public void constructor_should_craft_a_decimal()

      {

         SummationScienceExperiment foo = new SummationScienceExperiment(5,2);

         Assert.AreEqual(5, foo.DependentVariable);

         Assert.AreEqual(2, foo.IndependentVariable);

         Assert.AreEqual(2.5, foo.DivisionCalculation);

      }

      

      [TestMethod]

      public void update_should_craft_a_decimal()

      {

         SummationScienceExperiment foo = new SummationScienceExperiment(5, 2);

         foo.Update(4);

         Assert.AreEqual(5, foo.DependentVariable);

         Assert.AreEqual(4, foo.IndependentVariable);

         Assert.AreEqual(1.25, foo.DivisionCalculation);

      }

      

      [TestMethod]

      public void may_divide_zero()

      {

         SummationScienceExperiment foo = new SummationScienceExperiment(0, 2);

         Assert.AreEqual(0, foo.DependentVariable);

         Assert.AreEqual(2, foo.IndependentVariable);

         Assert.AreEqual(0, foo.DivisionCalculation);

      }

      

      [TestMethod]

      public void may_not_divide_by_zero()

      {

         Type type = typeof(SummationScienceExperiment);

         var infos = type.GetMethods(BindingFlags.NonPublic|BindingFlags.Instance);

         MethodInfo info = infos[3];

         SummationScienceExperiment foo = new SummationScienceExperiment(5, 2);

         Assert.AreEqual(info.Invoke(foo, new object[] { foo.DependentVariable, 0 }),null);

      }

   }

}

.Except

I stole the following from here.

double[] numbers1 = { 2.0, 2.1, 2.2, 2.3, 2.4, 2.5 };

double[] numbers2 = { 2.2 };

IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);

Tuple

...is a general purpose data shape in ASP.NET (http://www.dotnetperls.com/tuple)

Wednesday, February 8, 2012

Joel's definition of snake case

Snake case: punctuation is removed and spaces are replaced by single underscores. Normally the letters share the same case (either UPPER_CASE_EMBEDDED_UNDERSCORE or lower_case_embedded_underscore) but the case can be mixed.

cast string to enum

Colors colorValue = (Colors) Enum.Parse(typeof(Colors), colorString);

what to do when a file is not associated with Team Foundation Server

  1. right-click on the file in the Soultion Explorer and select "Exclude From Project"
  2. right-click on the file in the Soultion Explorer and select "Include In Project" (if the file does not appear in the Solution Explorer to select: try using the "Show All Files" toggle, an icon, at the top of the Solution Explorer)

Tuesday, February 7, 2012

Joel's DynamicCommandInvoker magic to empower wormholes

using System;

using System.Dynamic;

using System.Diagnostics;

using System.Linq;

using OurApp.Core.Repositories;

using OurApp.Core.Services;

namespace OurApp.Web.UI.CommandProcessing

{

   [DebuggerStepThrough]

   public class DynamicCommandInvoker: DynamicObject, IDynamicCommandInvoker

   {

      private readonly string CommandsNamespace = "";

      

      public DynamicCommandInvoker(string commandNamespace = "")

      {

         this.CommandsNamespace = commandNamespace;

      }

      

      public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args,

            out object result)

      {

         result = default(object);

         

         var processorName = BuildCommandProcessorName(binder.Name);

         var type = Type.GetType(processorName);

         

         
//ensure processor type exists and is present in local assembly

         if (type == null) throw new Exception(string.Format("please make sure your

               command processor class exists and is in the {0} namespace)",

               CommandsNamespace));

         

         var processor = Activator.CreateInstance(type, args);

         

         ResolveDependencies(processor);

         

         
//ensure processor is an ActionCommand

         if (processor == null || !(processor is CommandBase)) throw new Exception("please

               make sure your command processor inherits from ActionCommand");

         

         result = ((CommandBase)processor).Process();

         

         return true;

      }

      

      private void ResolveDependencies(object command)

      {

         var type = command.GetType();

         var props = type.GetProperties(System.Reflection.BindingFlags.Public |

               System.Reflection.BindingFlags.Instance).Where(prop => prop.CanWrite &&

               prop.PropertyType.GetInterfaces().Any(iface => iface == typeof(IRepository) ||

               iface == typeof(IService)));

         props.ForEach(prop =>

            {

               var value = ServiceLocator.Get(prop.PropertyType);

               if (value != null) prop.SetValue(command, value, null);

            });

      }

      

      private string BuildCommandProcessorName(string methodName)

      {

         string formatString = CommandsNamespace + ".{0}Command";

         return string.Format(formatString, methodName);

      }

   }

   

   public interface IDynamicCommandInvoker

   {

   }

}

change the title tag of a page with JavaScript

document.title = "The new title goes here.";

Monday, February 6, 2012

casting strings to integers or decimals with JavaScript

http://www.javascripter.net/faq/convert2.htm touches on casting strings to both decimal and integer values with JavaScript. parseFloat(string) and parseInt(string) do the needed.

JavaScript redirect

window.location = "/home/unsupportedbrowser/";

how to sniff browser specifications with jQuery

My last blog posting is terrible. Use this instead:

<div id="badbrowserspecifications"></div>

<script src="/Scripts/jquery-latest.js" type="text/javascript"></script>

<script type="text/javascript">

   var ua = $.browser;

   var txt = "<p>The browser you are using: ";

   if (ua.mozilla) {

      txt += "Firefox";

   } else {

      if (ua.msie) {

         txt += "Internet Explorer";

      } else {

         if (ua.safari) {

            ua.chrome = /chrome/.test(navigator.userAgent.toLowerCase());

            if (ua.chrome) {

               txt += "Chrome";

            } else {

               txt += "Safari";

            }

         } else {

            if (ua.opera) {

               txt += "Opera";

            } else {

               txt += "not Firefox, IE, Safari, Chrome, or Opera";

            }

         }

      }

   }

   txt += "<br />...versioned at: " + jQuery.browser.version + "</br>";

   txt += "......is insufficient for our application.</p>";

   document.getElementById("badbrowserspecifications").innerHTML = txt;

</script>

 
 

Sources for my change of heart:

how to sniff browser specifications with JavaScript

http://www.w3schools.com/js/js_browser.asp taught me that I may sniff my browser's specifications with JavaScript like so:

<div id="badbrowserspecifications"></div>

<script type="text/javascript">

   var txt = "<p>The browser you are using: " + navigator.appName + "<br />";

   txt += "...codenamed " + navigator.appCodeName;

   txt += " and versioned at: " + navigator.appVersion + "</br>";

   txt += "......is insufficient for our application.</p>";

   document.getElementById("badbrowserspecifications").innerHTML = txt;

</script>

how to get rid of the influence of the master page in a Razor view

@{

   ViewBag.Title = "Unsupported Browser";

   Layout = null;

}

<h1>@ViewBag.Title</h1>

Request.UserAgent

It looks like you may sniff what browser you are using on the C# side with Request.UserAgent.

Friday, February 3, 2012

what is this thing called?

I wish I understood the = () => operator one uses with Func in C#. I don't even know what it is called. It seems that you may prep a Func within a class (in this case DateHelper) like so:

public static Func<DateTime> Now = () => DateTime.UtcNow;

 
 

...and then sort of override it by way of a monkey patch like so in another situation (in this case in a test):

DateHelper.Now = () => new DateTime(2000, 1, 1);

boilerplate for command processor command tests


using System;

using System.Web.Mvc;

using OurApp.Core.Entities;

using OurApp.Web.UI.CommandProcessing;

using OurApp.Web.UI.CommandProcessing.Commands;

using OurApp.Web.UI.Models.InputModels.Orders;

using Microsoft.VisualStudio.TestTools.UnitTesting;

   

namespace OurApp.Tests.Unit.UI.CommandProcessing.Commands

{

   [TestClass]

   public class OrderCommandTestsTemplate : CommandTestBase

   {

      [TestMethod]

      public void boiler_plate_testing_skeleton_sample()

      {

         //input model

         var inputModel = new OrderInputModel();

         

         //output model

         var order = new Order();

         

         //mock your behaviors

         MocksRegistry.OrderRepositoryMock.Setup(x => x.Save(order));

         

         Func<ActionResult> success = () => new ViewResult();

         Func<ActionResult> fail = () => new ViewResult();

         

         //build target

         var command = new EditOrderCommand(inputModel,

               new Actions(null).OnSuccess(success).OnFailure(fail));

         

         //excersise sut

         command.Process();

         

         //expectations

         Assert.IsFalse(inputModel.Processed);

      }

   }

}

dive into a wormhole

This is how you would call our Command Processor from a controller action and dive into a wormhole:

[HttpPost]

public ActionResult Edit(OrderInputModel inputModel)

{

   return CommandProcessor.EditOrder(inputModel, Actions

      .OnSuccess(() => RedirectToAction("Index"))

      .OnFailure(() => View("Edit", BuildSelectListsForModel(inputModel))));

}

forbidden URL characters

# % & * { } \ : < > ? / + are not too healthy for URLs.

Thursday, February 2, 2012

Quartz.NET

Joel mentioned today that Quartz.NET is an enterprise job scheduling engine that we will start to use for, amongst other things, sending out notifications. Apparently it can do things like send out periodic notifications in a manner such that the notification rate will exponentially decay.

PUT with REST

Joel mentioned today that the appropriate way to do rest is via the PUT verb and that ASP.NET MVC does not approach REST in this manner. To use PUT in ASP.NET MVC you have to either empower it at IIS or Web.config.

comet

Joel mentioned today that comet is the code name for asynchronous http requests and that such an approach will eventually become depreciated once web sockets become more prevalent.

wormholes

Joel Holder hosted an informative meeting today on an approach to architecture that he has put together with Rafael Torres. Wormholes are key term in the new vision for the objects to come in our app. The way that CRUD around objects has materialized in our application has been unsophisticated so far and has come with a lot of problems. Going forward, as we start to build out the richer objects with lifecycles (the sort of objects that Eric Evans would consider entities) we want to get things right, and in particular we want to make things easier to test. Joel, pictured here, started the meeting by explaining why it was painful to have controllers interact directly with repositories in the DAL (Data Access Layer) within a Palermo Onion.

This is the traditional way to build an ASP.NET MVC app, but it is proving hard to test. Controllers are making calls to repositories and handing repository references down into models. Testing a controller requires going on a spelunking expedition for the things one needs to mock just in the name of getting a would-be test to the point where it fails instead of throwing an exception. Instead, Joel feels that controllers should have no collaborators that are managed objects (no repository references). He models his MVC approach on what he sees as a growing trend away from having controller do more than routing and he mentioned that in the node.js framework called Express that controllers were eventually renamed to be "routers" in a wise move. He feels a layer for Command Processors (light circles below) should sit between the rest of our onion and the Controllers (darker circles below) and that communication should occur through wormholes (red item below).

The Command Processors will in turn "talk" to service layers in our onion which will "talk" to the DAL and back. The wormholes make our Command Processors different than the Command Processors of Headspring which were baked before the dynamic objects of C# 4.0. The wormhole analogy suggests putting something into a tunnel and knowing that it will emerge from the tunnel somewhere, but not being able to see where from the entry point. Using the dynamic feature of C# 4.0, Joel has empowered the ability to call a method of any name on a Command Processor's DynamicCommandInvoker. If one calls .EditOrder for example, our app will try to find a file dubbed "EditOrderCommand.cs" to find an appropriate class for the "method" called, but to the controller doing the calling calls .EditOrder blind to as much. The controller calling .EditOrder basically asserts a desire to:

  1. invoke action x
  2. with model y
  3. and then redirect to z

ProcessCommand(), shown above, is the method inside any one particular command file that will do the deed and will be the one method to really test, test, test.

TempData is for redirects, and redirects only.

TempData["foo"] = "bar";

...is not going to linger as long as...

Session["foo"] = "bar";

 
 

http://stackoverflow.com/questions/1500402/when-to-use-tempdata-vs-session-in-asp-net-mvc suggests it is "for redirects, and redirects only."

things that don't suck

Wednesday, February 1, 2012

I wish there was a better way to see if a ViewBag variable existed in ASP.NET MVC 3 and 4 beyond a null check.

@if (ViewBag.ShouldShowSuccessMessage != null)

{

   ViewBag.ShouldShowSuccessMessage = null;

   <script type="text/javascript">

      showSuccess("Your changes have been saved!");

   </script>

}

It startled me to see a class in our app with numerous constructor signatures today.

I have not seen that in some time.

{ get; private set; } sabotages MVC model bindings

:(

getting used to AutoMapper

AutoMapper really helps makes the classes it maps to light and thus easy to test. Whenever I make a method in a class and then struggle to test it due to the fact that I cannot bridge the constructor in the class without mocking 101 things it is really frustrating. This is the sort of noise that does not make me want to write tests. AutoMapper helps alleviate this problem. That said, I wonder if I really should be placing a method inside of a DTO and then marveling at how easy it is to test. I probably should do the same work in a .ResolveUsing rule and just set a get-setter at the DTO, huh? I'll pick Rafael's brain when he gets in...