Tomasz Przychodzki
Tomasz Przychodzki

Reputation: 691

Knockout.js binding gets broken when property of ViewModel renamed

This is the first time I'm asking a question here, so please be tolerant :)

In an MVC web application powered up by knockout.js, I have, for clear example:

  1. Simple ViewModel class in C#:

    public class RetailCustomer
    {
        public DateTime BirthDate { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    
  2. Simple binding in knockout.js on MVC view:

    function CustomerCtxViewModel() {
        var self = this;
        self.FirstName = ko.observable('');
        self.LastName = ko.observable('');
        self.BirthDate = ko.observable('');
        $.getJSON("/api/RetailContext", function (data) {
            self.FirstName(data.FirstName);
            self.LastName(data.LastName);
            self.BirthDate(data.BirthDate);
        }
    }
    

Then I renamed the property BirthDate in RetailCustomer class to Birthdate, because Code Analysis told me so... and the binding doesn't work anymore of course, and the worst thing is I find it out only during runtime.

QUESTION: Are there any tools, techniques that would warn me early enough, during compile time or automated builds maybe, so that I can see my mistake before the app is running?

Upvotes: 1

Views: 261

Answers (3)

Michael Best
Michael Best

Reputation: 16688

I have not used it, but T4TS can generate a TypeScript interface definition from C# classes.

C#:

[TypeScriptInterface]
public class RetailCustomer
{
    public DateTime BirthDate { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

JavaScript:

$.getJSON("/api/RetailContext", function (data: T4TS.RetailCustomer) {
    self.FirstName(data.FirstName);
    self.LastName(data.LastName);
    self.BirthDate(data.BirthDate);
}

I also found TypeLITE which does much the same.

Upvotes: 1

jparaya
jparaya

Reputation: 1339

For this cases, you can use the @Html.NameFor helper, in case your data object (the JSON) is of the same type as the Model on your .cshtml file. If you want to validate syntax on compile time, you can edit the csproj and define MvcBuildViews to true. That way, you will know on compile time when Razor will fail. Check this question if you have problems with compilation.

Upvotes: 1

Roy J
Roy J

Reputation: 43881

super cool is correct: binding happens at runtime and the viewmodel is a dynamic object, so there is no practical way to ensure that the viewmodel and required bindings match up at compile/build time.

In principle, if you were using TypeScript, a build process could analyze the HTML and infer an Interface from it, which could then be applied to your viewmodel, but even that would be just the general case of applyBindings where it applies to the whole HTML doc. applyBindings can be used on individual HTML elements. It would be a very complicated system and nothing like it has been attempted as far as I know.

Upvotes: 1

Related Questions