Hi,
I’m using EF-Code first / MVC4 / C# for a number of projects now. Overall I’m really happy with the robustness and testability of the code, one kind of error however keeps popping up that I would like to obliterate once and for all.
Between different layers of the solution I’m passing (DB) identifiers, from controller to repository, from DB to viewmodel, from view back to controller and such. I found it quite easy to pass the wrong identifier to any such layer. Say a repository expects an Order-Id and receives an OrderStatus-Id. (They’re both basically int32) It seems to happen most of the time when someone refactors or rewrites a part of the code and inadvertently returns the wrong Id. Sometimes this is caught by unit/functional testing, but sometimes it only surfaces in production. This could be solved by simply passing an entire order-class and letting the receiver pick the ID from that, but I feel they’re a bit too heavy to be passing around all the time when all I need is the ID.
My solution so far:
Since I’m using poco classes I added a type Identifier class to each poco class with a sealed constructor and a function on the class to instantiate the new Identifier class. (See below) So an instance of the order-class can only create an orderIdentifier-class. In repositories and such I can now simply replace the Int with a type-safe identifier; for example OrderIdentifier.
POCO:
namespace x.Models
{
public class Customer
{
public int Id { get; set; }
// Lots of fields
public CustomerId Identifier()
{
return new CustomerId(this);
}
}
public sealed class CustomerId
{
// The identifier for read-only access
public int Value { get; private set; }
public CustomerId(Customer data)
{
Value = data.Id;
}
}
}
Repository:
public static string Config(CustomerId customerId)
This seems to work great except when I need to pass data from the view back to the controller. Ideally I’d write something like this:
Razor: (* using T4MVC)
@Html.ActionLinkButton("Edit",MVC.Customer.Config(CustomerItem.Identifier()))
Controller:
public virtual ActionResult Config(CustomerId CustomerId)
{
}
This works great with a primitive types like INT32, but not so with a complex object like CustomerId. (Since obviously MVC simply iterates all the properties), the resulting CustomerId remaines null.
Questions:
1) Is this a solid solution for attaining type safety for identifiers or are there other (better) solutions?
2) Is there a fix for this solution so it becomes usable from view>controller without relying on tempdata and the likes?