Thursday, 29 March 2012

WCF P2P example

Create empty c# Console project and add reference to System.ServiceModel

Message interface and class

[ServiceContract(CallbackContract = typeof(IMessage))]
public interface IMessage
{
    [OperationContract(IsOneWay = true)]
    void Send(string sender, string message);
}
class MessageImpl : IMessage
{
    public string Name { get; set; }
    public MessageImpl(string name)
    {
        Name = name;
    }
    public void Send(string sender, string message)
    {
        if (!Name.Equals(sender))
        {
            Console.WriteLine("{0}: {1}", sender, message);
        }
    }
}

Messenger

public class Messenger
{
    public string Name { get; private set; }
    public IMessage Channel;
    public IMessage Host;
    private DuplexChannelFactory<IMessage> _factory;
    private readonly AutoResetEvent _stopped = new AutoResetEvent(false);
    private readonly AutoResetEvent _started = new AutoResetEvent(false);
    public Messenger(string name, AutoResetEvent started)
    {
        Name = name;
        _started = started;
    }
    private void StartService()
    {
        var binding = new NetPeerTcpBinding();
        binding.Security.Mode = SecurityMode.None;
        var endpoint = new ServiceEndpoint(
            ContractDescription.GetContract(typeof(IMessage)),
            binding,
            new EndpointAddress("net.p2p://Messenger"));
        Host = new MessageImpl(Name);
        _factory = new DuplexChannelFactory<IMessage>(
            new InstanceContext(Host),
            endpoint);
        var channel = _factory.CreateChannel();
        ((ICommunicationObject)channel).Open();
            
        Channel = channel;
    }
    private void StopService()
    {
        ((ICommunicationObject)Channel).Close();
        if (_factory != null)
            _factory.Close();
    }
    public void Start()
    {
        Console.WriteLine("Starting Messenger");
        StartService();
        Console.WriteLine("Running Messenger");
        _started.Set();
        _stopped.WaitOne();
        Console.WriteLine("Stopping Messenger");
        StopService();
        Console.WriteLine("Stopped");
    }
    public void Stop()
    {
        _stopped.Set();
    }
}

Main Program

class Program
{
    static void Main(string[] args)
    {           
        if(args.Length<1)
        {
            Console.WriteLine("usage: Messenger <your-name>");
            return;                
        }
        var me = args[0];
        var started = new AutoResetEvent(false);
        var messager = new Messenger(me,started);
        var thread = new Thread(messager.Start) { IsBackground = true };
        thread.Start();
        started.WaitOne();
        while (true)
        {                
            string tmp = Console.ReadLine();
            if (tmp == "bye") break;
            messager.Channel.Send(me, tmp);
        }
        messager.Stop();
        thread.Join();            
    }
}

To start it run

Messenger.exe <your-name>

To stop type ‘bye’

Friday, 16 March 2012

MVC3 Restful JSON example

This is a Restful API for the MVC3 example from the previous post.

Get: GET /Api/Product/{id}
Create: POST /Api/Product
Update: PUT /Api/Product
Delete: DELETE /Api/Product/{id}

Create ApiController

public class ApiController : Controller
{
    DatabaseEntities entities = new DatabaseEntities();
    [HttpGet]
    [ActionName("Product")]
    public JsonResult Get(Guid id)
    {
        return Json(entities.Products.FirstOrDefault(x => x.Id == id), JsonRequestBehavior.AllowGet);
    }
    [HttpPost]
    [ActionName("Product")]
    public JsonResult Create(Product product)
    {        
        product.Id = Guid.NewGuid();
        entities.Products.AddObject(product);
        entities.SaveChanges();
        return Json(product);
    }
    [HttpPut]
    [ActionName("Product")]
    public JsonResult Update(Product product)
    {
        var current = entities.Products.FirstOrDefault(x => x.Id == product.Id);
        current.Name = product.Name;
        
        entities.SaveChanges();
        return Json(current);
    }
    [HttpDelete]
    [ActionName("Product")]
    public JsonResult Delete(Guid id)
    {
        entities.Products.DeleteObject(entities.Products.FirstOrDefault(x=>x.Id==id));
        entities.SaveChanges();
        return Json(true);
    }
}

And test it with Fiddler

-------
Create
-------
Url:
POST http://localhost:52292/Api/Product
Request Headers:
User-Agent: Fiddler
Host: localhost:52292
Content-Type: application/json; charset=utf-8
Content-Length: 21
Request Body:
{"Name":"Strawberry"}
-------
Get
-------
Url:
GET http://localhost:52292/Api/Product/5d2effcb-042d-4836-9125-c256ff955a73
Request Headers:
User-Agent: Fiddler
Host: localhost:52292
-------
Update
-------
Url:
PUT http://localhost:52292/Api/Product
Request Headers:
User-Agent: Fiddler
Host: localhost:52292
Content-Type: application/json; charset=utf-8
Content-Length: 62
Request Body:
{"Id":"848e791c-4161-447d-b6cb-7d9e1a2648a5",Name:"Raspberry"}
-------
Insert
-------
Url:
DELETE http://localhost:52292/Api/Product/5d2effcb-042d-4836-9125-c256ff955a73
Request Headers:
User-Agent: Fiddler
Host: localhost:52292

Thursday, 15 March 2012

Adding SQL Server CE 4.0 (Compact Edition) support to VS2010

Install VS2010 SP1 and SQL CE Tools for Visual Studio

Now you can add SQL Server Compact 4.0 Local Database to your project and connect to that database with ADO.NET Entity Data Model (Entity Framework 4).

More info on ScottGu’s Blog

How to use MVC3 with AJAX

To enable AJAX calls add this line to Views/Shared/_Layout.cshtml

<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>

Add new Products tab to menu in Views/Shared/_Layout.cshtml

<li>@Html.ActionLink("Product", "Index", "Product")</li>

Create new controller Controllers/ProductController.cs

DatabaseEntities is the Entity Framework 4 model with single table Product with 2 columns (Id uniqueidentity, Name nvarchar(100))

public class ProductController : Controller
{
    DatabaseEntities entities = new DatabaseEntities();
    public ActionResult Index()
    {
        return View(entities.Products);
    }
    [HttpPost]
    public ActionResult AddProduct(string name)
    {
        var product = new Product();
        product.Id = Guid.NewGuid();
        product.Name = name;
        entities.Products.AddObject(product);
        entities.SaveChanges();
        return PartialView("ProductList", entities.Products);
    }
    public ActionResult DeleteProduct(Guid id)
    {
        entities.Products.DeleteObject(entities.Products.FirstOrDefault(x=>x.Id==id));
        entities.SaveChanges();
        return PartialView("ProductList", entities.Products);
    }
}

Create 2 views /Views/Product/Index.cshtml

@using System.Data.Objects
@using MyProject.Data
@{
    ViewBag.Title = "Products";
}
@using (Ajax.BeginForm("AddProduct", "Product",new AjaxOptions()
    {
        UpdateTargetId = "ProductListDiv",
        HttpMethod = "POST"                                                                                  
    }))
{
    @Html.Label("Name: ") @Html.TextBox("name")
    <input type="submit" value="+" />     
}
<div id="ProductListDiv">
@Html.Partial("ProductList", (ObjectSet<Product>)Model)  
</div>

And /Views/Product/ProductList.cshtml

@using MyProject.Data
<table>
@{
    if (Model != null)
    {
        foreach (var m in Model)
        {
          <tr>
            <td>
                @Ajax.ActionLink("Delete", "DeleteProduct", "Product", new { Id = m.Id }, new AjaxOptions()
           {
               UpdateTargetId = "ProductListDiv",
               HttpMethod = "POST"
           })
           </td>
           <td>
                @m.Name
            </td>
        </tr>             
        }
    }
}
</table>

it should look more less like this

Mvc3Ajax