Thursday, April 23, 2015

Object Casting

On my most recent homework assignment I need to create a custom media formatter to return a response from my Web API service in a specific format that is based on XML.  Although I plan to write another topic on the whole custom media formatter, this is a quick hitter to discuss how to cast a variable of type object into an IEnumerable of another type (assuming the object is actually an IEnumerable of that other type).

When you inherit from the BufferedMediaTypeFormatter class you have the option to override the WriteToStream method, which accepts a Type, object, Stream, and HttpContent.  In my case, the object could be either a single instance or a List of the same type of object (in this case it was a model named BaseViewModel).

What I needed to do was handle writing the output differently if I had a single object compared to a list of objects.  So I did this:


   1:  if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (List<>))
   2:  {
   3:      var objectType = type.GetGenericArguments()[0];
   4:      var genericListType = typeof(List<>).MakeGenericType(objectType);
   5:      var listOfObjects = (IEnumerable)Activator.CreateInstance(genericListType);
   6:  }

Now, this isn't exactly what I did because I did always know that my object would be an instance of BaseViewModel, but this little bit of code did allow me to cast my object into a list of the underlying object of the object that was passed.  Wait, I'm not sure that last part made sense.

Basically, since a List technically inherits from object, I was able to (through those three lines) cast my object into a List.  We'll just go with that.  It works.

C# Tuples

Tuples in C# provide a way for "one" object to have multiple types and values.  I use this a lot when I'm returning results from one method to another so I can check whether the call was successful (with a bool) and also return a value (like an error message) to the caller.

You use Tuples by specifying - through the use of generic type parameters - what the data types will be of each "item" in the tuple.  Each tuple can have seven items, and an eighth item that is another tuple.

In our home-grown ORM solution I've implemented tuples as the return type of the methods that map data from the database to the objects:



   1:  Tuple<TParent, TChild1, TChild2, TChild3, TChild4, TChild5, TChild6> Get
   2:              <TParent, TChild1, TChild2, TChild3, TChild4, TChild5, TChild6>(string sprocName,
   3:                                                                              List<SqlParameter> parameters = null,
   4:                                                                              string schema = "dbo",
   5:                                                                              CommandType commandType =
   6:                                                                                  CommandType.StoredProcedure)
   7:              where TParent : class
   8:              where TChild1 : class
   9:              where TChild2 : class
  10:              where TChild3 : class
  11:              where TChild4 : class
  12:              where TChild5 : class
  13:              where TChild6 : class;

This method will return a single object with a total of 7 items where there is one parent object that has six properties that are each a complex object.  When I invoke this method, I do so like this:



   1:  var data = Get<Person, List<Pet>, List<Car>, Person, List<Person>, House, Employer>("Person_GetDetails", new List<SqlParameter> {new SqlParameter("@ID", 12345)});
   2:   
   3:  var person = data.Item1;
   4:  person.Pets = data.Item2;
   5:  person.Cars = data.Item3;
   6:  person.Spouse = data.Item4;
   7:  person.House = data.Item5;
   8:  person.Employer = data.Item6;

This way I can pass back a single Person object from my repository method.  There are, of course, other uses, but this is a quick example of how to use tuples.

JavaScript Object.keys

JavaScript has a useful little function called Object.keys(object) where you pass an object and get the "keys" (properties) of that object.  Once you have those, you can enumerate the values of those keys on the object you want.  Check it out:

function ListKeyValues(input) {
    var keys = Object.keys(input);
    
    for(var i = keys.length; --i >= 0;){
        console.log(input[keys[i]]);
    }
}

This is obviously a contrived example, but here's the usage:


ListKeyValues({Name: "John Doe", Age: 32});

Generic Type Parameters in C#

Generic type parameters are used all over the place in built-in constructs in C#, such as
   1:  IEnumerable<T>
and
   1:  List<T>
which you've probably used before.

But you can create your own methods to use generic type parameters, too.  You may be asking why you'd want to do this.  Well, the short answer is compile-time support for methods that return an instance of an object only known at runtime.  That's one reason anyway, and it's the reason I'll demonstrate here.

Let's say you have two classes:

   1:  public class ClassOne
   2:  {
   3:      public string FirstName { get; set; }
   4:  }
   5:   
   6:  public class ClassTwo
   7:  {
   8:      public int Id { get; set; }
   9:  }

And a method that can return an instance of either class:

   1:  public ClassOne | ClassTwo BuildAnObject()
   2:  {
   3:  }

(Hint: that won't compile)

So if you know that your method will return one or the other, you could write two separate methods, taking the exact same parameters, but returning a different type.  That would technically work (if you named the methods differently anyway), but it's kind of a pain in the butt.  Instead, you can change your method signature to use generic type parameters to specify the return type when you call the method:


   1:  public T BuildAnObject<T>()
   2:  {
   3:      return default(T);
   4:  }

At this point, "T" represents whatever you want it to represent.  This way, if you created a third class you could use the exact same method by specifying ClassThree as T when you make the call:

   1:  public void BuildIt()
   2:  {
   3:      var result = BuildAnObject<ClassOne>();
   4:   
   5:      var firstName = result.FirstName;
   6:  }

Right there you can see we have compile-time support for result.

Friday, April 17, 2015

Web API UrlHelper (DefaultApi)

I wrote a helper to get the location to return in the Location header of an Add/Create request.  At first I wrote this (because I found it on the Internet so it has to be true, right?):

   1:  var urlHelper = new UrlHelper(request);
   2:  var uri = urlHelper.Route("DefaultApi", new { id });
   3:  return uri != null ? new Uri(uri, UriKind.Relative) : null;

The problem with that was that my Location header was being returned with the Add endpoint, which is obviously not right:

Location: /api/grade/add/1

To fix this, I created a new route in the WebApiConfig and then switched one line of code to use the new route:


   1:  config.Routes.MapHttpRoute(
   2:      name: "GetApi",
   3:      routeTemplate: "api/{controller}/get/{id}",
   4:      defaults: new { action = "Get", id = RouteParameter.Optional }
   5:  );


   1:  var urlHelper = new UrlHelper(request);
   2:  var uri = urlHelper.Route("GetApi", new { id });
   3:  return uri != null ? new Uri(uri, UriKind.Relative) : null;

That does it.  Now my header is right:

Location: /api/grade/get/1

Monday, April 6, 2015

ng-if or ng-show

I just came across something that I figured out quickly enough, but really threw me off for a few minutes.

In Angular, I know that ng-if and ng-show aren't interchangeable, but in most situations they seem to be pretty interchangeable and I don't know the differences between them - other than ng-if doesn't render things if the "if" condition isn't met.

I have a table that shows/hides a <th> and a corresponding <td> based on an ng-if.  That was all working fine until I needed to change the <tr> inside of which the <td> exists to also rely on (a differnet) ng-if.  Once I added that, I found that the condition on which the <td> relied wasn't updating when the underlying model value was being changed, but only in the header evaluation.  That meant the <th> was staying put while the <td> was toggling, which caused me a bit of confusion.

A coworker just stopped by to tell me it has to do with the fact that ng-if creates a new scope and ng-show doesn't, but we both agree that this still seems like a weird scenario.  An example is below.


This doesn't work:
<table>
    <tr>
        <th ng-show="OptionA == true">Column 1 Header</th>
        <th ng-show="OptionA == false">Column 2 Header</th>
        <th>Column 3 Header</th>
    </tr>
    <tr ng-if="OptionB == true">
        <td ng-show="OptionA == true">Column 1 Row 1 Data</td>
        <td ng-show="OptionA == false">Column 2 Row 1 Data</td>
        <td>Column 3 Row 1 Data</td>
    </tr>
    <tr ng-if="OptionB == false">
        <td colspan="3">Row 2 Merged Data</td>
    </tr>
</table>


But this does:
<table>
    <tr>
        <th ng-show="OptionA == true">Column 1 Header</th>
        <th ng-show="OptionA == false">Column 2 Header</th>
        <th>Column 3 Header</th>
    </tr>
    <tr ng-show="OptionB == true">
        <td ng-show="OptionA == true">Column 1 Row 1 Data</td>
        <td ng-show="OptionA == false">Column 2 Row 1 Data</td>
        <td>Column 3 Row 1 Data</td>
    </tr>
    <tr ng-show="OptionB == false">
        <td colspan="3">Row 2 Merged Data</td>
    </tr>
</table>