Created
October 13, 2012 23:40
-
-
Save mythz/3886615 to your computer and use it in GitHub Desktop.
Your First ASP.NET Web API Products Example vs ServiceStack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Tutorial example from: | |
* Your First ASP.NET Web API (C#): | |
* http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api | |
*/ | |
namespace HelloWebAPI.Controllers | |
{ | |
public class ProductsController : ApiController | |
{ | |
Product[] products = new Product[] | |
{ | |
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, | |
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, | |
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M } | |
}; | |
public IEnumerable<Product> GetAllProducts() | |
{ | |
return products; | |
} | |
public Product GetProductById(int id) | |
{ | |
var product = products.FirstOrDefault((p) => p.Id == id); | |
if (product == null) | |
{ | |
throw new HttpResponseException(HttpStatusCode.NotFound); | |
} | |
return product; | |
} | |
public IEnumerable<Product> GetProductsByCategory(string category) | |
{ | |
return products.Where( | |
(p) => string.Equals(p.Category, category, | |
StringComparison.OrdinalIgnoreCase)); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Enhancing your services: | |
* - Added Get by categoryName | |
* - Added Find by Price | |
*/ | |
namespace HelloWebAPI.Controllers | |
{ | |
public class ProductsControllerV2 : ApiController | |
{ | |
Product[] products = new Product[] | |
{ | |
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, | |
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, | |
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M } | |
}; | |
public IEnumerable<Product> GetAllProducts() | |
{ | |
return products; | |
} | |
public Product GetProductById(int id) | |
{ | |
var product = products.FirstOrDefault((p) => p.Id == id); | |
if (product == null) | |
{ | |
throw new HttpResponseException(HttpStatusCode.NotFound); | |
} | |
return product; | |
} | |
public Product GetProductByName(string categoryName) | |
{ | |
var product = products.FirstOrDefault((p) => p.Name == categoryName); | |
if (product == null) | |
{ | |
throw new HttpResponseException(HttpStatusCode.NotFound); | |
} | |
return product; | |
} | |
//Extending existing services by adding more RPC method signatures | |
public IEnumerable<Product> GetProductsByCategory(string category) | |
{ | |
return products.Where( | |
(p) => string.Equals(p.Category, category, | |
StringComparison.OrdinalIgnoreCase)); | |
} | |
public IEnumerable<Product> GetProductsByPriceGreaterThan(decimal price) | |
{ | |
return products.Where((p) => p.Price > price); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Same implementation as above but using Coarse-grained, Batch-ful interfaces, less + more re-usable services: | |
namespace WebApi.ProductsExample | |
{ | |
//Design of new services based on calling semantics and Return type, e.g. Find* filters results, whilst Get* fetches unique records: | |
public class FindProducts : IReturn<List<Product>> | |
{ | |
public string Category { get; set; } | |
public decimal? PriceGreaterThan { get; set; } | |
} | |
public class GetProduct : IReturn<Product> | |
{ | |
public int? Id { get; set; } | |
public string Name { get; set; } | |
} | |
public class ProductsService : IService | |
{ | |
readonly Product[] products = new[] | |
{ | |
new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 }, | |
new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, | |
new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M } | |
}; | |
public object Get(FindProducts request) | |
{ | |
var ret = products.AsQueryable(); | |
if (request.Category != null) | |
ret = ret.Where(x => x.Category == request.Category); | |
if (request.PriceGreaterThan.HasValue) | |
ret = ret.Where(x => x.Price > request.PriceGreaterThan.Value); | |
return ret; | |
} | |
public object Get(GetProduct request) | |
{ | |
var product = request.Id.HasValue | |
? products.FirstOrDefault(x => x.Id == request.Id.Value) | |
: products.FirstOrDefault(x => x.Name == request.Name); | |
if (product == null) | |
throw new HttpError(HttpStatusCode.NotFound, "Product does not exist"); | |
return product; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Notes: | |
// - No Code-Gen: Same generic service client used for all operations | |
// - When Custom Routes are specified it uses those, otherwise falls back to pre-defined routes | |
// - IRestClient interface implemented by JSON, JSV, Xml, MessagePack, ProtoBuf Service Clients | |
// - Service returns IEnumerable[Product] but JSON, JSV serializers happily handles List[Product] fine | |
private const string BaseUri = "http://localhost:1337"; | |
IRestClient client = new JsonServiceClient(BaseUri); | |
"\nAll Products:".Print(); | |
client.Get(new FindProducts()).PrintDump(); | |
/* All Products: | |
[ | |
{ | |
Id: 1, | |
Name: Tomato Soup, | |
Category: Groceries, | |
Price: 1 | |
}, | |
{ | |
Id: 2, | |
Name: Yo-yo, | |
Category: Toys, | |
Price: 3.75 | |
}, | |
{ | |
Id: 3, | |
Name: Hammer, | |
Category: Hardware, | |
Price: 16.99 | |
} | |
] | |
*/ | |
List<Product> toyProducts = client.Get(new FindProducts { Category = "Toys" }); | |
"\nToy Products:".Print(); | |
toyProducts.PrintDump(); | |
/* Toy Products: | |
[ | |
{ | |
Id: 2, | |
Name: Yo-yo, | |
Category: Toys, | |
Price: 3.75 | |
} | |
] | |
*/ | |
List<Product> productsOver2Bucks = client.Get(new FindProducts { PriceGreaterThan = 2 }); | |
"\nProducts over $2:".Print(); | |
productsOver2Bucks.PrintDump(); | |
/* Products over $2: | |
[ | |
{ | |
Id: 2, | |
Name: Yo-yo, | |
Category: Toys, | |
Price: 3.75 | |
}, | |
{ | |
Id: 3, | |
Name: Hammer, | |
Category: Hardware, | |
Price: 16.99 | |
} | |
] | |
*/ | |
List<Product> hardwareOver2Bucks = client.Get(new FindProducts { PriceGreaterThan = 2, Category = "Hardware" }); | |
"\nHardware over $2:".Print(); | |
hardwareOver2Bucks.PrintDump(); | |
/* Hardware over $2: | |
[ | |
{ | |
Id: 3, | |
Name: Hammer, | |
Category: Hardware, | |
Price: 16.99 | |
} | |
] | |
*/ | |
Product product1 = client.Get(new GetProduct { Id = 1 }); | |
"\nProduct with Id = 1:".Print(); | |
product1.PrintDump(); | |
/* Product with Id = 1: | |
{ | |
Id: 1, | |
Name: Tomato Soup, | |
Category: Groceries, | |
Price: 1 | |
} | |
*/ | |
"\nIt's Hammer Time!".Print(); | |
Product productHammer = client.Get(new GetProduct { Name = "Hammer" }); | |
productHammer.PrintDump(); | |
/* It's Hammer Time! | |
{ | |
Id: 3, | |
Name: Hammer, | |
Category: Hardware, | |
Price: 16.99 | |
} | |
*/ | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks