Tuesday, January 31, 2012

using .ResolveUsing with AutoMapper

If you had an AutoMapper map like so:

Mapper.CreateMap<Person, PersonInputModel>().ForMember(personInputModel => personInputModel.FullName, person => person.ResolveUsing<PersonNameResolver>());

 
 

.ResolveUsing would allow you to reach out to another method to undertake a tricky translation.

using System.Linq;

using OurApp.Core.Entities;

using AutoMapper;

namespace OurApp.Web.UI.Config.AutoMapper.Resolvers

{

   public class OrderStatusReasonResolver : ValueResolver<Person, string>

   {

      protected override string ResolveCore(Person source)

      {

         var fullName = source.FirstName + " " + source.LastName;

         return fullName.Trim();

      }

   }

}

Monday, January 30, 2012

sabotage the ability to tab to a control with tabindex="-1"

If you are doing something hacky and you need an "invisible" HTML input that is:

  1. not a hidden input type
  2. not hidden by a style of display: none;

You can always move the control off the page's edge with a style of margin-left:-9999px;

...but, yes, the control is accessible by way of tabbing unless you take steps to sabotage the ability to tab to the control with: tabindex="-1"

only show something in a Razor view if debugging

@if (Context.IsDebuggingEnabled)

{

   
whatever

}

Friday, January 27, 2012

Here is some interesting AJAX we started to roll and then abandoned today!

This controller action...

public RenderJsonResult Foo(Guid id)

{

   var program = ProgramRepository.GetById(id);

   var ppMap = new Dictionary<ProgramPlan, string>();

   program.ProgramPlans.ForEach(pp =>

      {

         ppMap.Add(pp, pp.NameStaticAttribute.GetSelectedValue(pp.Id).ToString());

      });

   var result = ppMap.Keys.Select(pp => new

   {

      Id = pp.Id,

      Name = ppMap[pp],

      Offerings = pp.ProgramOfferings.Select(po => new { po.Id, po.Name })

   });

   return RenderJson(result);

}

 
 

...made some new objects and returned them as JSON which kind of looked like this:

{\"PreventCyclicRedundancy\":false,\"Result\":[{\"Plan\":{\"Id\":\"01583ab6-3b8a-4af7-ac68-9fe500ec99a0\",\"Name\":\"alpha\",\"Offerings\":[{\"Id\":\"2660ce9a-73b2-406a-9ff6-9fe500ee6617\",\"Name\":\"one\"},{\"Id\":\"294eac05-83d2-42a6-9cdf-9fe500ee9f17\",\"Name\":\"two\"},{\"Id\":\"80c4ac8b-b2b8-4043-8207-9fe500eef13d\",\"Name\":\"three\"}]}},{\"Plan\":{\"Id\":\"bdf3d257-573d-4685-88d5-9fe500ecaffc\",\"Name\":\"beta\",\"Offerings\":[]}},{\"Plan\":{\"Id\":\"926cf94f-c546-4ec4-a860-9fe500ed8e9a\",\"Name\":\"gamma\",\"Offerings\":[{\"Id\":\"4e729423-3ff9-4abc-bb3c-9fe500ef8ffc\",\"Name\":\"four\"},{\"Id\":\"c3879ef4-80ed-40f9-8a7d-9fe500efc899\",\"Name\":\"five\"}]}}]}

 
 

There was a Razor view like this...

<div class="contentBlock" id="qux">

</div>

<script src="/whatever.js" type="text/javascript"></script>

<script type="text/javascript">

   var programId = '@Model.Program.Id';

   var planLinksContainerSelector = 'qux';

   bar(programId, planLinksContainerSelector);

</script>

 
 

...which reached out to a .js file which called on the Controller Action:

function bar(programId, containerSelector) {
   $.ajax({
      url: '/Program/Foo',
      data: 'id=' + programId,
      success: function (result) {
         var container = $(planLinksContainerSelector);
         _.each(result, function (plan) {
            var planLink = $('<a />');
            planLink.attr('href', '/programplan/edit/?programId=' + programId + '&id=' + plan.Id);
            planLink.text(plan.Name);
            container.append(planLink);
            _.each(plan.Offerings, function (offering) {
               //do offs here
            });
         });
      },
      error: function (a, b, c) {
      }
   });
}

Thursday, January 26, 2012

demystify NuGet error messages

Today Jorge and I encountered this really vague NuGet error in Visual Studio:

Error 7 The command ""C:\AMD\trunk\src\Tools\nuget" update -self
"C:\AMD\trunk\src\Tools\nuget" install "C:\AMD\trunk\src\AMD.Avalanche.Web.UI\packages.config" -o "C:\AMD\trunk\src\Packages" -source file://BUILDS/nuget-lib" exited with code 1. AMD.Avalanche.Web.UI

 
 

Jorge suggested I open a command window and paste in the contents of the outer most quotes, namely:

"C:\AMD\trunk\src\Tools\nuget" update -self
"C:\AMD\trunk\src\Tools\nuget" install "C:\AMD\trunk\src\AMD.Avalanche.Web.UI\packages.config" -o "C:\AMD\trunk\src\Packages" -source file://BUILDS/nuget-lib

 
 

This revealed better error messages:



I'm not that in love with NuGet. I would prefer just keeping the needed .dlls in the lib folder. Rafael did mention that, when installing some .dlls, that NuGet will doctor up a Web.config file as is appropriate to be accommodating. I guess that is one thing in favor of the automation. I'm mostly turned off however. :(

of what bubbles up from repositories

The beauty of the typical repository pattern is you know if something has been "popped off" (forgive my injection of SMTP slang) when you encounter it in another layer. For example consider going into a method and finding:

var bars = foo.Bars;

 
 

If foo is handed in from another method and Bars is a collection of Bar objects on foo, how can we know if the Bars have been lazy loaded by NHibernate yet or not. We can't. We have to start walking upstream to see if there is any place previously in code where foo.Bars was used. Grrr. If there is a policy in which everything that comes over from repositories has already been loaded, then this isn't a problem. A variation of this problem can happen with IQueryable too. When IQueryables are allowed into other layers from the repositories, one does not know, when looking at many spots in code, if an IQueryable had been popped off to a list or not somewhere upstream of the line of code at hand. To counter this pattern, it is probably best to only have objects already cast to lists come over the wall from repositories.