Not compatible with the latest KendoUI release - 2013.1.419.340

Apr 23, 2013 at 12:53 AM
The normalizing of special characters to underscores breaks in some instances.

I just upgraded my application to use the latest KendoUI widgets and T4MVC threw 20 errors, to a previously clean application.

Here is one of the generated classes in T4MVC.cs that references one of the styles in Kendo.
public static class Black {
    private const string URLPATH = "~/Content/kendo/2013.1.419/Black";
    public static string Url() { return T4MVCHelpers.ProcessVirtualPath(URLPATH); }
    public static string Url(string fileName) { return T4MVCHelpers.ProcessVirtualPath(URLPATH + "/" + fileName); }
    public static readonly string editor_png = Url("editor.png");
    public static readonly string imagebrowser_png = Url("imagebrowser.png");
    public static readonly string loading_image_gif = Url("loading-image.gif");
    public static readonly string loading_gif = Url("loading.gif");
    public static readonly string slider_h_gif = Url("slider-h.gif");
    public static readonly string slider_v_gif = Url("slider-v.gif");
    public static readonly string sprite_png = Url("sprite.png");
    public static readonly string sprite_2x_png = Url("sprite@2x.png");
    public static readonly string sprite_2x_png = Url("sprite_2x.png");
}
The last two static variables are the same, even though they are generated from different values.

Is this something that can be fixed fairly easily? Otherwise I'll have to downgrade my project to the previous version of KendoUI. Let me know if you need more info.

Thanks,

King Wilder
Coordinator
Apr 23, 2013 at 1:01 AM
Look at the Sanitize method on line 1230. Maybe you can tweak it to work for you. Right now, it replaces invalid chars by underscores, so in this sprite@2x case above it ends up conflicting with the other file.
Apr 23, 2013 at 1:37 AM
David, thanks for the pointer. I was able to tweak the Sanitize method to work. Here's my solution, I don't know if it's ready for prime time, but it removed all error messages.
static string Sanitize(string token)
{
    if (token == null) return null;

    token = Regex.Replace(token, @"[@]", "_at", RegexOptions.IgnoreCase);  <-- this is new

    // Replace all invalid chars by underscores
    token = Regex.Replace(token, @"[\W\b]", "_", RegexOptions.IgnoreCase);

    // If it starts with a digit, prefix it with an underscore
    token = Regex.Replace(token, @"^\d", @"_$0");

    // Check for reserved words
    // TODO: Clean this up and add other reserved words (keywords, etc)
    if (token == "Url") token = "_Url";

    return token;
}
I first check for the "@" sign and then replace it with "_at", then the rest is the same. There's probably a more elegant way of handling this, but it works for me at the moment.

Thanks,

King Wilder
Apr 23, 2013 at 1:42 AM
Actually I modified this a little so it doesn't blow up on other "@" instances. This is my new final answer. :^)
    token = Regex.Replace(token, @"@2x", "_at2x", RegexOptions.IgnoreCase);
This targets this single anomaly and it will still underscore other "@" signs.
Coordinator
Apr 23, 2013 at 1:48 AM
That works. The hard part is to find a general solution that could go in T4MVC. There are two goals that conflict a little bit:
  1. Get rid of invalid characters without causing conflicts
  2. Come up with names that don't look too crappy
It would be easy to solve #1 by doing some crazy replacements, but then we'd have nasty variable names. Maybe one option is to not change the default algorithm, but allow the user to do some custom handling from a method in T4MVC.tt.hooks.t4.

The problem with changing t4mvc.tt is that it makes it harder to update to newer versions.
Apr 23, 2013 at 2:18 AM
I agree, that integrating this into the master source could produce problems. I'm actually satisfied with this solution. By making this simple change in this single line, I can have more control over these types of modifications that may not necessarily be in every application.

With that said, since I have a subscription to the Telerik Suite of components, I will be using KendoUI in all of my MVC projects, and I will have to implement this in each project, unless they change it yet again in a future version. But really, this would take just a second to copy and paste from a previous application, so I'm not disappointed at the solution to the problem.

But if you do come up with a solution, those of us using KendoUI will be grateful.
Developer
May 6, 2013 at 6:01 PM
David,
I think this solution is acceptable and would like to see it in the main build. It does not look 'too bad' and solves a real issue.
Coordinator
May 6, 2013 at 7:20 PM
Yes, I'm fine with having a customizable hook in T4MVC.tt.hooks.t4 if someone wants to make that change and send a PR.
Developer
May 6, 2013 at 8:17 PM
What about just making THIS change to the main source. Don't see why this would cause a problem and/or be worth another hook.
Coordinator
May 6, 2013 at 8:24 PM
I'm confused. 'THIS' referring to what exactly? Do you mean the "@2x" above?

Seems a bit hacky to hard code that in for this one specific case, no? Though I guess if:
  • this situation is very rare
  • Many people are using KendoUI and hitting it
  • it's just the one KendoUI file that has the issue
Then we could consider baking in the hack for convenience. But I don't really like it! :)
Developer
May 6, 2013 at 8:29 PM
Yes, that was what I meant.
Yes, it is a bit hacky.
Yes, I have never ran into it before.
KendoUI is very popular.
The one KendoUI file is the only one with an issue.

I don't really like it either.

Possibly 'real' solution:

Root cause is the 'renaming' to a valid identifier may conflict with another file that already exists with that identifier.
When the T4 script is running and it generates the name for a file - we could stick that name into an array (array created for that folder).
Then when generating new names, we just check to see if the name is already in the array..if it is, we add extra underscores until it is unique.

What do you think of that (and I am completely asking for your help on the t4 side of this code for that - can it be done easily and where would that go)?
Coordinator
May 7, 2013 at 2:46 AM
One way to implement this is to have ProcessStaticFilesRecursive create a hash table and pass it to all its recursive calls to ProcessStaticFilesRecursive to check for conflicts at that node (i.e. one new hash table per node in the tree).
Developer
May 7, 2013 at 3:29 AM
Yeah, something like that. I know you have not had a lot of time to put into this project, but would this change be something you are willing to tackle?
That code would normally be something I would take a stab at changing, but with all the T4 mess, it is quite difficult to follow. Other than that, this method does not seem that bad to implement and is a correct and clean solution..?
Coordinator
May 7, 2013 at 6:29 AM
Yes, I can take a look if there is no other taker. :) But it may not be for a few days are things are a bit crazy here (but then again, they always are!).
Coordinator
May 8, 2013 at 7:38 AM
Ok, it's in 3.6.2. Would be great if you could both give it a try! I ended up reimplementing this fix as part of it.
Developer
May 15, 2013 at 7:47 AM
No issues with latest kendo or anything. Thanks again.