By david on December 06, 2011

 

In ASP .NET MVC, using ModelState object for server side validation is quite simple.

In the controller method:

if (string.IsNullOrEmpty(model.FirstName))
    ModelState.AddModelError("FirstName", "Please enter the First Name");

 

And in the view:

@Html.TextBoxFor(m => m.FirstName)
@Html.ValidationMessageFor(m => m.FirstName)

How do you add validation error for collection property? It ought to be simple as well, but searching the Internet, I could not seem to find any example. So, I thought posting it here that it might useful for others.

In the controller method:

for (int i=0; i< model.Cars.Count; i++)
{
    if (String.IsNullOrWhitespace(model.Cars[i].Make))
    {
        ModelState.AddModelError(String.Format("Cars[{0}].Make", i), "Please enter the car's make/model.");
    }
}

And in the view:

@for (int i = 0; i < Model.Drugs.Count; i++)
{
    <!-- some other fields... -->
    <input name="Cars[@i].Make" type="text" value="@Model.Cars[i].Make" />
    @Html.ValidationMessageFor(m => m.Cars[i].Make)    
}

The key is that the key we pass to the ModelState’s error collection dictionary matches the rendered tag for identifying the Html element to put the validation message. In above case, the @Html.ValidationMessageFor(m => m.Cars[i].Make) – render to this in my browser:

<span class="field-validation-valid" data-valmsg-for="Cars[0].Make" data-valmsg-replace="true"></span>

 

In this case, the data-valmsg-for matches the key we pass in the ModelState’s error collection dictionary above (e.g. “Cars[i].Make”).

By david on November 11, 2011

 

In Entity Framework 4 – by default Lazy Loading is disabled when creating Object Context. However, if we use the Entity Framework tool to create new model and the corresponding generated class, Lazy Loading is enabled in the object context’s constructor.

Hence, if we want to disable Lazy Loading by default, it would be quite painful every time we update the Model and regenerate the Entity Framework classes, because we would need to go back to the generated Object Context class and reset the LazyLoadingEnabled property to false.

Fortunately, we can instead edit the .edmx file so that the generated Object Context class would have LazyLoadingEnabled property to set to false by default. This option is not available in the Designer UI.

Open the .edmx file as XML file, and edit the following:

<EntityContainer Name="EntitiesContainerName" annotation:LazyLoadingEnabled="false">

Next time you regenerate the classes, the generated Object Context will have by default set LazyLoadingEnabled to false in its constructors.

By david on September 27, 2011

Recently we are working on a project that process and generate EDI document. We are using XSLT to transform internal data format to the EDI Trading Partner’s format. One feature in XSLT that makes live easier is the ability to use extension to write custom logic in code. We use this to do lookup function, conversion (date and time format), etc. during the mapping. Since we are using .NET, we are using the msxsl:script extension.

Below is a code snippet of an XSLT that uses msxsl:script to embed code in the XSLT document.

<?xml version="1.0" encoding="utf-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:var="http://schemas.palador.com/Edi/var" version="1.0"
                xmlns:converter="urn:converter">
  <xsl:output omit-xml-declaration="yes" version="1.0" method="xml" />
  <xsl:template match="/FR8Invoice">
    <Interchange>
      <!-- ommitted for clarity -->
      <N1>
        <xsl:variable name="var:v48" select="converter:CustomerType(string(./Type))" />
        <N101>
          <xsl:value-of select="$var:v48" />
        </N101>
      </N1>
      <!-- ommitted for clarity -->
    </Interchange>
  </xsl:template>
  <msxsl:script language="C#" implements-prefix="converter">
    <![CDATA[
    public string CustomerType(string input){
      string customerType = "  ";
 
      switch (input)
      {
          case "Shipper":
              customerType = "SH";
              break;
          case "Consignee":
              customerType = "CN";
              break;
          case "Invoicee":
              customerType = "BT";
        break;
    }
    return customerType;
}
]]>
  </msxsl:script>
</xsl:stylesheet>
By david on June 15, 2011

 

It is quite common to add an existing record into a collection of another entity. For example, adding an existing Student into a Course. Prior to Entity Framework 4, using Entity Framework – would need to load the Student entity, then add it to the Course object, then save the context. In Entity Framework 4, by using stub entities, as long as we have the primary key(s) for the entity to add to, we do not need to load the entire entity anymore.

Thanks to this post and this post, here is what we come up with:

protected void T AttachToOrGet<T>(string entitySetName, T entity)        
{
    ObjectStateEntry entry;
    bool attach = false;
    if (Context.ObjectStateManager.TryGetObjectStateEntry(
            Context.CreateEntityKey(entitySetName, entity),
            out entry))
    {
        attach = entry.State == EntityState.Detached;
        entity = (T)entry.Entity;
    }
    else
    {
        attach = true;
    }
    if (attach)
    {
        Context.AttachTo(entitySetName, entity);
    }
    return entity;
}
 
public void AddStudent(int courseId, int studentId)
{
    Course course = Context.Courses.Where(c => c.CourseId == courseId).FirstOrDefault();
    if (course != null)
    {
        if (!course.Students.Any(s => s.StudentId == studentId))
        {
            Student stubStudent = AttachToOrGet("Students", new Student { StudentId = studentId });                        
            course.Students.Add(stubStudent);
            Context.SaveChanges();
        }            
    }
}

 

Also do not forget to make sure the bridge table CourseStudent (in case many-to-many relationship between Student and Course) has PKs, otherwise EntityFramework will give you this error message:

“Error from EF (need to have PK) - Unable to update the EntitySet because it has a DefiningQuery and no <InsertFunction> element exists in the <ModificationFunctionMapping> element to support the current operation.”

By david on May 12, 2011

In the past few months we have been working on TransactVM, a replication-based disaster recovery for Hyper-V™ Virtual Machines. It is integrated with NetApp Storage Systems using the SDK that NetApp provided.

In this blog, we are going to review our experience in integrating with the NetApp Storage Systems.

The SDK comes with client API module for numerous platforms – .NET, Java, C/C++, Perl, etc. In our case, we are using the .NET client API.

The API is a simple client-server RPC-like calls using web service. There is only one main method call – InvokeElem(command). It returns the result. Both the command and the result is in xml format. It also comes with some helper methods – however, no custom types whatsoever (those we define ourselves once we understand the NetApp API model). An example will look like this:

NaServer server = new NaServer(storageAddress, 1, 0) { Style = NaServer.AUTH_STYLE.RPC };
NaElement command = new NaElement("snapmirror-get-status");
command.AddChildElement(new NaElement("location", volume));
try
{
    NaElement snapmirrorStatusXml = server.InvokeElem(command);
    if (snapmirrorStatus == null)
        return SnapmirrorState.Null;
 
    NaElement snapmirrorStatusInfo = snapmirrorStatus.GetChildByName("snapmirror-status-info");
    string state = snapmirrorStatusInfo.GetChildContent("state");
    if (String.Equals(state, "snapmirrored", StringComparison.OrdinalIgnoreCase))
        return SnapmirrorState.Snapmirrored;
    if (String.Equals(state, "broken-off", StringComparison.OrdinalIgnoreCase))
        return SnapmirrorState.BrokenOff;
    if (String.Equals(state, "uninitialized", StringComparison.OrdinalIgnoreCase))
        return SnapmirrorState.Uninitialized;
    if (String.Equals(state, "quiesced", StringComparison.OrdinalIgnoreCase))
        return SnapmirrorState.Quiesced;
    if (String.Equals(state, "source", StringComparison.OrdinalIgnoreCase))
        return SnapmirrorState.Source;
    if (String.Equals(state, "unknown", StringComparison.OrdinalIgnoreCase))
        return SnapmirrorState.Unknown;
}
catch (NaApiFailedException e)
{
    throw new NetAppException(String.Format(CultureInfo.CurrentCulture, "NaApiFailedException ErrorNo: {0}", e.ErrorNo), e);
}

 

It seem a bit cumbersome to have to format command and parse the result when calling the API. However, once we get used to it, it’s quite fun to work with.

Both NetApp Data OnTap OS and the API is quite robust. The API help file is quite extensive. The error codes and messages (along with the API help file) are quite helpful in figuring out problems when they arise.

Integration with Storage Device like NetApp is an important facet in TransactVM – it is providing the bridge between Hyper-V and the storage devices used in conjunction with - to provide replication-based disaster recovery.

We are looking forward to getting this product out the door (Beta is coming very soon)!

By david on March 01, 2011

 

Recently we need to move a Visual Studio solutions (along with all its associated files) from one Team TFS Project to another. There is no "move” functionality across Team TFS Project that I know of to do something like this.

The steps required are actually simple:

1. Remove all Source Control binding from the original Solution and its associated Project files.

2. Open the Solution.

3. Add the Solution to the new Team TFS Project source control.

The question, how do we do step 1 without manual labor? If I have significant amount of .csproj files in the Solution, we do not want to do that by hand one-by-one.

The solution turns out to be quite simple – there is a feature in Visual Studio (2010) that would help us, but it requires some manual step first (which is not very laborious at all).

Here is how we did it:

1. Setup so that when we opened the Solution file, Visual Studio will take it offline (I simply unplug my network cable).

2. Open the solution, click yes when it asked whether we would like to go offline mode.

3. Save the Solution. Exit.

4. We copied the whole folder and its subfolders (we want to keep everything original intact).

5. We opened the Solution file (in the new copied folder).

6. Click File menu, Source Control…, and Change Source Control…

7. It will ask whether we would like to remove source control binding. Say yes.

8. We inspected the .sln and .csproj files (a few) – and nothing suspicious there (it looked like it cleaned out all the source control binding information).

9. Restore back environment to connect to the Team TFS server.

10. On the Solution, right click and select Add Solution to Source Control.

11. We are done.

Note: I noticed afterward that while in Online mode, there is actually an Unbind option under Source Control… | Change Source Control option. We did not try that. It might work the same.

By david on January 25, 2011

 

When we serve an HTTP 302 – Redirect response, we do not have the ability to set / put cookie in the response. Last week, we encountered a situation where we need a Redirect behavior, but in the same time we also need to be able to put (multiple) cookies in the HTTP response.

Using ASP .NET MVC, it was quite an elegant solution to simulate redirect and preserving the ability to put/set cookie in the response.

We created a custom ActionResult which simply use JavaScript to simulate the redirect.

Here is the code snippet:

public class JavaScriptRedirectResult : ActionResult
{
    private string RedirectUrl { get; set; }
 
    public override void ExecuteResult(ControllerContext context)
    {
        var response = context.HttpContext.Response;
        var responseContent = new StringBuilder();
        responseContent.AppendLine("<HEAD>");
        responseContent.AppendLine("<SCRIPT language=\u0022JavaScript\u0022>");
        responseContent.AppendLine(String.Format("window.location=\u0022{0}\u0022;", RedirectUrl));
        responseContent.AppendLine("</SCRIPT>");
        responseContent.AppendLine("</HEAD>");
        response.Write(responseContent.ToString());
    }
 
    public JavaScriptRedirectResult(string redirectUrl)
    {
        RedirectUrl = redirectUrl;
    }
}

And here is an example of using it:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SomeControllerMethod()
{       
    return new JavaScriptRedirectResult(Url.Action("OtherControllerMethod"));
}
By david on December 21, 2010

 

When using .NET encryption library in web application and it is deployed in load balanced/server farm environment, we need to setup a static machine key at the application level. Not doing this will result potential problem in the decryption process.

By default, ASP .NET will auto-generate the machine key used for encryption when the ASP .NET web application start. As a result, not only you will get different machine key every time the web application gets restarted (e.g. some of our deployment are to Azure and that always means IIS restart on upgrade) – the same application process on different server machine (or server vms) would have different encryption key as well.

ASP .NET uses encryption and put the encrypted value in the cookie to be used on the round-trip. The potential problem is this, if your first request containing encryption key hit server 1 then the subsequent request hit server 2, ASP .NET won’t be able to decrypt the data since the web app on server 2 has different encryption key.

Same thing if you restart the IIS and it happens that the encrypted data persist in the cookie across sessions (for example, ASP .NET MVC AntiForgeryToken persist the encrypted data across sessions, at least by default).

Here is one example of what the web.config will look like to setup machine key at application level. See documentation at MSDN for more detail.

<system.web>

<machineKey validationKey="[validation key]"
                decryptionKey="[decryption key]"
                validation="SHA1"
                decryption="AES" />

</system.web>

By david on November 16, 2010

Ah... the buzzword. Scrum and Agile. Yes, we are doing it at Palador.

In the last 6 months or so – we, at Palador, have had 3 different projects executed using Scrum. And they were all successful.

What is the measure of this success? Here are my 'poor man' definitions, they are nothing fancy and have no scientific metrics – simply some common sense:

  • The customer(s) are happy with what we deliver- this means we would most likely get their business again in the future.
  • The development team (programmer, designer, QA) is happy - no burn out at end of iterations and team is eager to start in the beginning of each iterations – this means we would most likely get sustained performance in the long run (if not even better), one key factor for repeat success.
  • The management is happy – this means that we would have more support to continue our journey in adopting Scrum and agile development.

We have a long way to go. There is a lot we can and need to improve. Just because we are successful in the past 6 months, does not mean we already "get it". It also did not mean that we were not successful before. It just means that as a collective – ranging from development Team, Product Owner, and Management (stakeholders) – we agree that we are doing things better than before.

As I reflect what has happened in the last 6 months, here are some key-factors that (at least in our case) has allowed us to have good result in adopting Scrum:

  • Strong Support from Management
  • Buy-In from Team
  • Product Owner that “gets it”
  • Supporting Tool
  • Scrum Master who can coach those involved in the Scrum process.

Strong Support from Management: One tenet of Scrum is to "leave the Team alone". And Management did exactly that. What do I mean by that? A lot of things, but few that comes to mind:

  • Management is committed to enable Team to focus on the Iteration Backlog (refrain from changing Iteration Backlog as well as minimize work request that is outside the Iteration Backlog).
  • Management let the Team to self-organize - this allowed Team to adapt relatively faster to change– e.g. technical challenges or roadblock, uncovering previously unknown requirement, etc.
  • The Team was free to ask (or not to ask) for outside help – this empower the Team to figure things out themselves, to put into place technical solution that they deem are best for a given problem.

Buy-In from Team: There has been positive talk about (the ideas embodied in Scrum) among the development Teams. Hence, when we "officially" adopted Scrum in the pilot project - the Team members were excited and ready to go. They still didn't know exactly what it meant - but they embraced the ideas.

Product Owner that “gets it”: A key tenet in agile development – is quick and dynamic information flow between the developers and the Product Owner. Our Product Owner was quite responsive to the Team’s questions. Another key tenet in agile development is accuracy in communication. Our Product Owner embraced the idea of face-to-face communication, white-boarding, and scribbling on paper. He was committed to make sure the Team understands what they need to understand to deliver quality product.

Supporting Tool: Ken Schwaber in his Google TechTalk 2006 said – “"So, it's an idea that if we didn't have the technology, it would have gone nowhere." We need tools to get the job done. Without tools that allow us to do things rapidly, we can’t deliver in the speed that we did. One I want to highlight here is VSTS 2010 and VSTS Process for Agile Software Development 1.0. It is not perfect, many features to be wished for still, but it works for what we need. Its seamless integration to Excel 2010 is godsend.

Scrum Master who can coach: Ideas and philosophy behind Scrum/Agile- is not as easy as it might look. Ken Schwaber said: "Some Scrum Masters just don’t get it, no matter how much they’ve read about Scrum. Scrum is a simple, straightforward set of practices, rules, and roles, as introduced in Chapter 1 and further described in the Appendixes of this book. But the philosophy behind Scrum is somewhat less simple and can sometimes be difficult to understand." - Agile Project Management with Scrum –Ch. 3. Hence it is important to have Scrum Master "who understand the principles behind agile and Scrum" so he/she can coach those involved and increase the chance of the agile mindset be embraced and practiced.

We have a long way to go. There is still a LOT we can and need to improve. Just because we are successful in the past 6 months, does not mean we already "get it". It just means that we are doing things better than before. And in agile development, improvement is a constant (at least we try to).

By david on November 01, 2010

Dependency Injection is a powerful pattern. However, often it is not easy to answer the question: Should I use
Dependency Injection or not? Some would simply skip this question and either use Dependency Injection anywhere
they have an interface definition or in the other side of spectrum simply don't use it and planning to simply
modify the code (which means everywhere) - when they have a need to.

One principle in Lean methodology is to delay technical decision as late as possible. The answer to this
kind of question can be delayed with no risk by using Factory Method. (Assuming one can not answer at
the moment whether it would be worth using Dependency Injection or not at the moment).

Here are the sample code

  public static class ProductFactory
  {
    public static IProduct CreateProduct()
    {
      return new Product();
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      var product = ProductFactory.CreateProduct();
      product.DoSomething();
    }	
}

Notice here that everywhere in the application code, we are going to use the ProductFactory.CreateProduct() to get
an instance of an IProduct - and at the moment we are not using Dependency Injection.

However, when in the future we decide we need a Dependency Injection, we can simply do something like this
(using Unity - assumed we have UnityFactory helper class).

public static class ProductFactory
{
	public static IProduct CreateProduct()
	{
		return UnityFactory.Current.Resolve<IProduct>();
	}
}

This way, only one place in the application code we make a change and now everywhere Dependency Injection is in place.