1. June 2013 20:32 by admin in
.net, DRY, jQuery, MVC, typescript, Weld
Imagine you have a MVC controller exposing a Person as following:
public JsonResult GetPerson(int id)
{
return Json(new Person
{
First = "Barack",
Last = "Obama"
},JsonRequestBehavior.AllowGet);
}
Now I want to use this client side. I want to update my "first" span with the First property of the person I get back from the server. After messing around I came up with the following:
$(document).ready(function() {
$.getJSON("/Person/GetPerson/", { id: 4 }, function(data) {
$("#first").text(data.First);
});
});
This took me five minutes to get right (which JQuery method? -> Google, how to pass data? -> find example, plus a typo in the first/First member). Five minutes of stupid getting right what should be trivial. Why not let the compiler help? So using Weld I change my server side method to this :
[AjaxMethod]
public JsonResult<Person> GetPerson(int id)
{
return new JsonResult<Person>(Json(new Person
{
First = "Barack",
Last = "Obama"
}, JsonRequestBehavior.AllowGet)); ;
}
Basically I wrap my JsonResult in a generic wrapper JSonResult<T> (included with Weld) so that Weld knows what type to expect. Next I add the AjaxMethod Weld attribute. Client side I use TypeScript and use the generated proxy class.
/// <reference path="Weld/PersonController.ts" />/// <reference path="typings/jquery/jquery.d.ts" />
$(document).ready(function () {
PersonController.prototype.GetPerson(2, (person) => {
$("#first").text(person.First)
});
});
Now person is a JavaScript object or a TypeScript 'any' type. No, Person is a fully defined TypeScript interface with a First and Last member just like my C# class. Here's the generated code:
/// <reference path="../typings/jquery/jquery.d.ts" />
class PersonController
{
GetPerson(id: number, callback: (data: Person) => any)
{
var url = "/Person/GetPerson";var data = { id: id };
$.ajax({
url: url,
type : "POST",
data: data,
success: callback,
});
}
}
interface Person
{
First: string;
Last: string;
}
As always in the end there is still JavaScript code generated which you can easily debug. Weld code is simple and clean. Easy huh? And there are more benefits:
- If I remove or rename my action-method the TypeScript compiler will detect my breaking client side code at compile time. If you just use javascript you will (hopefully) find out at runtime.
- If I add or remove properties from my Person class my changes will cascade to the clientside immediately.
- I get a nice interface clientside making code completion really work
- No more Googling JQuery methods
- This is more DRY (Don't Repeat Yourself). For example if you don't like JQuery you can build a Weld template using a different method. Regenate and you are ready
1. June 2013 19:30 by martijn in
.net, jQuery, MVC, typescript, Weld In this post I want to talk about a little tool called Weld I wrote to make integrating client-side TypeScript and server side MVC C# easy.
Imagine you have a server-side method that calculates some value you want to use client side. In this sample project I want to calculate the sum of two values I have in input fields.
Server-side I have this action-method in my home controller.
public int Sum(int x,int y)
{
return x + y;
}
Now to access this method client I just need to add a Weld attribute. For this I first install Weld using NuGet.
Just “Install-Package Weld” in your NuGet package manager console. This will install Weld as well a TypeScript.Compile and JQuery typings into your project.
TypeScript.Compile auto compiles all your typescript files post-build. This enables you to detect any problems caused by server side changes.
The basic process :
- Normal compilation
- Weld generates TypeScript code for the classes your decorated with Weld attributes
- TypeScript compiles all files in your project with build actions 'TypeScriptCompile'
For this sample I add the AjaxMethod (Weld.Attributes.AjaxMethod) attribute to the ‘Sum’ action.
Compile the project. Weld now has generated a proxy class for my home controller. I just need to include it and used it in the project. It is located in the /Scripts/Weld folder.
I add the generated homecontroller.ts to my project. I my main TypeScript file I write the following to hook it all up:
/// <reference path="Weld/HomeController.ts" />/// <reference path="typings/jquery/jquery.d.ts" />
$(document).ready(function () {
$("#btnSum").click(function () {
HomeController.prototype.Sum($("#number1").val(), $("#number2").val(), (result) => {
$("#result").text(result);
});
});
});
As you can see the details of the Ajax communication are handled by weld and you get a nice interface to your server side API :)