WCF Restful CRUD
CREATING WCF REST SERVICE PROYECT
lets créate a CRUD proyect (backend and front-end using MVC to consume Service).
- from the SQL Server database you will have to be set a DB and the table with records on there.
and i filled them as follow:
id Name Price Quantity CreationDate
1 Personal 1000 2 2015-01-01
2 Samsung 500 3 2015-01-02
3 Apple 900 6 2015-01-04
- now lets pass to visual studio:
First of all, let us créate a WCF Service proyect on Visual Studio:
- First, ad ADO.NET Entity Framework Model to have all the entities on our proyect.
- Add a new class to créate the entity Product
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CRUDwithJson
{
public class Product
{
public int id
{
get; set;
}
public string Name
{
get; set;
}
public string Price
{
get; set;
}
public string Quantity
{
get; set;
}
public string CreationDate
{
get; set;
}
}
}
- Now let us créate the Service contract :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace CRUDwithJson
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IServiceProduct" in both code and config file together.
[ServiceContract]
public interface IServiceProduct
{
[OperationContract]
[WebInvoke(Method = "GET" , UriTemplate ="findall", ResponseFormat = WebMessageFormat.Json)]
List<Product>findAll();
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "find/{id}", ResponseFormat = WebMessageFormat.Json)]
Product find(string id);
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "create", ResponseFormat = WebMessageFormat.Json,
RequestFormat =WebMessageFormat.Json)]
bool create(Product product);
[OperationContract]
[WebInvoke(Method = "PUT", UriTemplate = "edit", ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
bool edit (Product product);
[OperationContract]
[WebInvoke(Method = "DELETE", UriTemplate = "delete", ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json)]
bool delete(Product product);
}
}
- and then implement on the Service class (.svc )the Service contract as stated down below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace CRUDwithJson
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "ServiceProduct" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select ServiceProduct.svc or ServiceProduct.svc.cs at the Solution Explorer and start debugging.
public class ServiceProduct : IServiceProduct
{
public bool create(Product product)
{
using (MyDemoEntities mde = new MyDemoEntities())
{
try
{
ProductEntity pe = new ProductEntity();
pe.Name = product.Name;
pe.Price = product.Price;
pe.Quantity = product.Quantity;
mde.ProductEntities.Add(pe);
mde.SaveChanges();
return true;
}
catch
{
return false;
}
}
}
public bool delete(Product product)
{
using (MyDemoEntities mde = new MyDemoEntities())
{
try
{
int id = Convert.ToInt32(product.id);
ProductEntity pe = mde.ProductEntities.Single(p => p.id == id);
mde.ProductEntities.Remove(pe);
mde.SaveChanges();
return true;
}
catch
{
return false;
}
}
}
public bool edit(Product product)
{
using (MyDemoEntities mde = new MyDemoEntities())
{
try
{
int id = Convert.ToInt32(product.id);
ProductEntity pe = mde.ProductEntities.Single(p => p.id == id);
pe.Name = product.Name;
pe.Price = product.Price;
pe.Quantity = product.Quantity;
mde.SaveChanges();
return true;
}
catch
{
return false;
}
}
}
public Product find(string id)
{
using (MyDemoEntities mde = new MyDemoEntities())
{
int nid = Convert.ToInt32(id);
return mde.ProductEntities.Where(pe => pe.id == nid).Select(pe => new Product
{
id = pe.id,
Name = pe.Name,
Price = pe.Price,
Quantity = pe.Quantity
}).First();
};
}
public List<Product> findAll()
{
using (MyDemoEntities mde = new MyDemoEntities())
{
return mde.ProductEntities.Select(pe => new Product
{
id = pe.id,
Name = pe.Name,
Price = pe.Price,
Quantity = pe.Quantity
}).ToList();
};
}
}
}
- Now in the webconfig file we may want to type the right binding and set it as httpweb enabled :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit https://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
<httpModules>
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
</httpModules>
</system.web>
<system.serviceModel>
<services>
<service name="CRUDwithJson.ServiceProduct" behaviorConfiguration="CRUDwithJson_Behavior">
<endpoint address="" binding="webHttpBinding" contract="CRUDwithJson.IServiceProduct"></endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="CRUDwithJson_Behavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="ApplicationInsightsWebTracking" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler" />
</modules>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true" />
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
<connectionStrings>
<add name="MyDemoEntities" connectionString="metadata=res://*/ModelMyDemo.csdl|res://*/ModelMyDemo.ssdl|res://*/ModelMyDemo.msl;provider=System.Data.SqlClient;provider connection string="data source=MININT-2JMB56K\ADK;initial catalog=mydemo;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
if you point to the svc. file on IE https://localhost:1120/ServiceProduct.svc you will see how it return Json information needed when Consulting to https://localhost:1120/ServiceProduct.svc/findall
result:
[{"CreationDate":null,"Name":"Personal","Price":"1000","Quantity":"2","id":1},{"CreationDate":null,"Name":"Samsung","Price":"500","Quantity":"3","id":2},{"CreationDate":null,"Name":"Apple","Price":"900","Quantity":"6","id":3}]
and if you consult only one ítem https://localhost:1120/ServiceProduct.svc/find/1
result:
{"CreationDate":null,"Name":"Personal","Price":"1000","Quantity":"2","id":1}
it Works! lets créate the client now.
CONSUMING THE WCF REST SERVICE:
- Creating an MVC Proyect as a client.
- change the routing config file and place "Product" as stated down below:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Product", action = "Index", id = UrlParameter.Optional }
);
}
}
}
- on the model folder we need to créate the "Product object" to interact with it:
add a class and fill with this information:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace CRUDWithJSONInWCF_MyRestClient.Models
{
public class Product
{
[Display(Name="id")]
public int id
{
get; set;
}
[Display(Name = "Name")]
public string Name
{
get; set;
}
[Display(Name = "Price")]
public string Price
{
get; set;
}
[Display(Name = "Quantity")]
public string Quantity
{
get; set;
}
[Display(Name = "CreationDate")]
public string CreationDate
{
get; set;
}
}
}
- Also créate another class as "ProductServiceClient" class :
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
namespace CRUDWithJSONInWCF_MyRestClient.Models
{
public class ProductServiceClient
{
private string BASE_URL = "https://localhost:1120/ServiceProduct.svc/";
public List<Product> findAll()
{
try
{
var webclient = new WebClient();
var json = webclient.DownloadString(BASE_URL + "findall");
var js = new JavaScriptSerializer();
return js.Deserialize<List<Product>>(json);
}
catch
{
return null;
}
}
public Product find(string id)
{
try
{
var webclient = new WebClient();
string url = string.Format(BASE_URL + "find/{0}", id);
var json = webclient.DownloadString(url);
var js = new JavaScriptSerializer();
return js.Deserialize<Product>(json);
}
catch
{
return null;
}
}
public bool create(Product product)
{
try
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Product));
MemoryStream mem = new MemoryStream();
ser.WriteObject(mem, product);
string data = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
WebClient webClient = new WebClient();
webClient.Headers["Content-type"] = "application/json";
webClient.Encoding = Encoding.UTF8;
webClient.UploadString(BASE_URL + "create", "POST", data);
return true;
}
catch
{
return false;
}
}
public bool edit (Product product)
{
try
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Product));
MemoryStream mem = new MemoryStream();
ser.WriteObject(mem, product);
string data = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
WebClient webClient = new WebClient();
webClient.Headers["Content-type"] = "application/json";
webClient.Encoding = Encoding.UTF8;
webClient.UploadString(BASE_URL + "edit", "PUT", data);
return true;
}
catch
{
return false;
}
}
public bool delete(Product product)
{
try
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Product));
MemoryStream mem = new MemoryStream();
ser.WriteObject(mem, product);
string data = Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
WebClient webClient = new WebClient();
webClient.Headers["Content-type"] = "application/json";
webClient.Encoding = Encoding.UTF8;
webClient.UploadString(BASE_URL + "delete", "DELETE", data);
return true;
}
catch
{
return false;
}
}
}
}
- Now let us créate the controller class :
add a new controller on controller directoty and place this :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using CRUDWithJSONInWCF_MyRestClient.Models;
using CRUDWithJSONInWCF_MyRestClient.ViewModels;
namespace CRUDWithJSONInWCF_MyRestClient.Controllers
{
public class ProductController : Controller
{
public ActionResult Index()
{
ProductServiceClient psc = new ProductServiceClient();
ViewBag.listProducts = psc.findAll();
return View();
}
[HttpGet]
public ActionResult Create()
{
return View("Create");
}
[HttpPost]
public ActionResult Create(ProductViewModel pvm)
{
ProductServiceClient psc = new ProductServiceClient();
psc.create(pvm.Product);
return RedirectToAction("Index");
}
public ActionResult Delete (string id)
{
ProductServiceClient psc = new ProductServiceClient();
psc.delete(psc.find(id));
return RedirectToAction("Index");
}
[HttpGet]
public ActionResult Edit(string id)
{
ProductServiceClient psc = new ProductServiceClient();
ProductViewModel pvm = new ProductViewModel();
pvm.Product = psc.find(id);
return View("Edit", pvm);
}
[HttpPost]
public ActionResult Edit(ProductViewModel pvm)
{
ProductServiceClient psc = new ProductServiceClient();
psc.edit(pvm.Product);
return RedirectToAction("Index");
}
}
}
- to interact between view and model let us créate a folder and call it as ViewModels:
and then add a class ProductViewModel.cs filling this as follow:
using CRUDWithJSONInWCF_MyRestClient.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace CRUDWithJSONInWCF_MyRestClient.ViewModels
{
public class ProductViewModel
{
public Product Product
{
get;set;
}
}
}
- so, now let us créate the view as index.class in View directory :
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<a href="@Url.Action("Create", "Product")">Add a new Product Please</a>
<br /><br /><br />
<table cellpadding="2" cellspacing="2" border="1">
<tr>
<th>Id</th>
<th>Name</th>
<th>Price</th>
<th>Quantity</th>
</tr>
@foreach (var product in ViewBag.listProducts)
{
<tr>
<th>@product.id</th>
<th>@product.Name</th>
<th>@product.Price</th>
<th>@product.Quantity</th>
<th>
<a href="@Url.Action("Delete", "Product", new { id = product.id})">Delete</a>
<a href="@Url.Action("Edit", "Product", new { id = product.id})">Edit</a>
</th>
</tr>
}
</table>
<div>
</div>
</body>
</html>
if you browse you will be able to see the table with all content from data base.
- now add the Edit view and place this :
@{
Layout = null;
}
@model CRUDWithJSONInWCF_MyRestClient.ViewModels.ProductViewModel
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Edit</title>
</head>
<body>
@using (Html.BeginForm("Edit", "Product"))
{
<table cellpadding="2" cellspacing="2">
<tr>
<td>@Html.LabelFor(model => model.Product.id)</td>
<td>
@Html.ValueFor(model => model.Product.id)
@Html.HiddenFor(model => model.Product.id)
</td>
</tr>
<tr>
<td>@Html.LabelFor(model=>model.Product.Name)</td>
<td>@Html.TextBoxFor(model => model.Product.Name)</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.Product.Price)</td>
<td>@Html.TextBoxFor(model => model.Product.Price)</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.Product.Quantity)</td>
<td>@Html.TextBoxFor(model => model.Product.Quantity)</td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Save"/></td>
</tr>
</table>
}
<div>
</div>
</body>
</html>
- and last but no lest add the créate view :
@{
Layout = null;
}
@model CRUDWithJSONInWCF_MyRestClient.ViewModels.ProductViewModel
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Create</title>
</head>
<body>
@using (Html.BeginForm("Create", "Product"))
{
<table cellpadding="2" cellspacing="2">
<tr>
<td>@Html.LabelFor(model=>model.Product.Name)</td>
<td>@Html.TextBoxFor(model => model.Product.Name)</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.Product.Price)</td>
<td>@Html.TextBoxFor(model => model.Product.Price)</td>
</tr>
<tr>
<td>@Html.LabelFor(model => model.Product.Quantity)</td>
<td>@Html.TextBoxFor(model => model.Product.Quantity)</td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Save"/></td>
</tr>
</table>
}
<div>
</div>
</body>
</html>
Now if you browse you will be able to CRUD :
hope this can be usefull to you. thanks :)
Comments
- Anonymous
August 08, 2016
:) - Anonymous
September 07, 2016
exellent! thank you - Anonymous
May 05, 2017
wao, exellent! amigo