We're getting ready to create a project where we want to expose data to the public via OData and Soap (to let the users of our API's choose which format they want to consume). I know that the Web API allows you to expose a public action method that has an IQueryable as the return type, and that T value then become queryable from OData. The problem is that our web server sits in a DMZ, and will NOT have direct access to the Entity Framework, thus no direct access to IQueryable. Access to the internal network is done through WCF.
Is there a way to receive the values from an OData call, and proxy those through parameters to the internal network? I've been scouring the internet, and so far, haven't found anything useful. I was thinking I'd just grab the query string directly, pass that through to the internal network, and there, use something like PredicateBuilder to create an EF expression tree, and return the data. That would work, but I'm wondering if there's a better way.
Thanks in advance!
It's very easy to handle the OData queries yourself and you can return IEnumerable, IList, PageResults or whatever. Here's an example:
[HttpGet]
[ActionName("Example")]
public IEnumerable<Poco> GetExample(ODataQueryOptions<Poco> queryOptions)
{
//simulate an EF DbSet for the example
var data = new Poco[] {
new Poco() { id = 1, name = "one", type = "a" },
new Poco() { id = 2, name = "two", type = "b" },
new Poco() { id = 3, name = "three", type = "c" }
};
var t = new ODataValidationSettings() { MaxTop = 2 };
queryOptions.Validate(t);
var s = new ODataQuerySettings() { PageSize = 1 };
var results = queryOptions
.ApplyTo(data.AsQueryable(), s) as IEnumerable<Poco>;
return results;
}
public class Poco
{
public int id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
I’d suggest creating a WCF Data Service using your Entity Framework model and make that service available to the DMZ server. I’ve been running a web site, on a DMZ server, with this configuration for a few years now and it has worked well. However, I will admit that WCF Data Services does have some limitations (compared to direct access to Entity Framework) on how you can compose your IQueryable queries but seems to improve with each release.
Related
I have get method, which should return users and there permissions. I have a users object and a permissions object, which i populate like this:
List<Users> users= MtFacade.GetUser(query);
List<UserPermissions> upermissions = MtFacade.GetUserPermission(User.Identity.Name);
My API controller returns a HttpResponse, for which I need to send back two lots of JSON, using the two objects.
I can do this if i return just one at a time, but how do i combined the two?
Wrap them in a class that encompasses properties of their types.
I'm sure you've already figured this out since you've accepted the answer, but in case it helps you or others that see this question here is a code example:
// this would be your class that can encompass the two objects
public class UsersAndPermissions
{
public List<User> Users { get; set; }
public List<UserPermissions> Permissions { get; set; }
}
In your web api method use the above class like this
var usersAndPerms = new UsersAndPermissions
{
Users = MtFacade.GetUser(query),
Permissions = MtFacade.GetUserPermission(User.Identity.Name)
};
// now your json that you return from the web api has both of the objects data
return usersAndPerms;
I have been given to develop a web application that can have multiple presentation layers, currently its on the web but soon to be on desktops and other platforms. So I searched around on how to do it best. I have found that its better to use a layered approach.
I am thinking to have BLL as a web-service which could be accessed by different PLs. The BLL will be accessing DAL for data specific operations.
So far so good, but I was thinking of using ASP.NET MVC for the web app. Now I am a bit confused because the "controllers" essentially contain the business logic, right.
Is it a good option ? If i do follow the same path, using MVC and the above mentioned layers, my controllers wont necessarily contain the BLL but will only be, kinda dummies.
Is it the right way to do it?
These are the recommended layers:
Presentation (MVC, WPF, Whatever):
contains only presentation logic (never includes business logic) the controller only handle communication with application/services layer to co-ordinate communication.
Distributed Services (Remote Facade):
as you will have many clients, some of them would be windows apps and others are web apps, it is recommended to create a remote service layer (WCF services or web services) which exposes business layer to consumers (preferable send and receive DTOs).
Application Layer:
a layer which handles the communication with domain layer, and co-ordinate transaction logic and technical services, and if you are using DTOs it translates domain objects into DTOs and vice versa
Domain Layer:
contains entities and value objects, this is the core of business logic designed in terms of object oriented domain objects encapsulating data and logic. it also could contains repository interfaces if using repository pattern. and domain services for logic that does not fit into a single entity.
Data Access:
using ORM like NHibernate or EF or whatever data access techniques to map entities into database tables.
Infrastructure / Common:
infrastructure code and cross cutting technical services like logging
I will try to give a tiny example about each layer:
a hypothetical incomplete example say you want to activate a purchase order
Presentation Layer (MVC):
public class PurchaseOrderController
{
public ActionResult ActivateOrder(int id)
{
var response = _orderManagementService.ActivateOrder(id); // Call distributed service (Web Service)
if(response.Succeed)
return new SuccessActionResult();
else
return new FailedActionResult(response.Reason);
}
}
Distributed Service Layer (Web Service):
public class OrderManagementWebService : IOrderManagementService
{
private readonly IOrderExecutionService _orderService;
public OrderManagementWebService(IOrderExecutionService orderService)
{
_orderService = orderService; // Order Service from application service
}
public ActivationResult ActivateOrder(int id)
{
var response = _orderService.ActivateOrder(id); // Call the application layer to execute the logic
if(
}
}
Application Layer:
public class OrderExecutionService : IOrderExecutionService
{
private IOrderRepository _orderRepository;
public OrderExecutionService(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
public ActivationResult ActivateOrder(int id)
{
var order = _orderRepository.GetById(id); // Get the order from repository
try
{
order.Activate(); // Call business logic inside the order entity
return new ActivationResult { Success = true } ;
}
catch(ActivationException ex)
{
LogFactory.GetLog().Exception(ex); // Call log from infrastructure layer
return new ActivationResult { Success = false, Reason = ex.Message } ;
}
}
}
Domain Layer:
public class PurchaseOrder : Entity
{
// Properties and fields (Data)
public int Id { get; private set; }
public Customer Customer { get; private set; }
// Methods (contains business logic)
public void Activate()
{
if(Customer.IsBlacklisted)
throw new InvalidCustomerException(...);
if(_lineItems.Count == 0)
throw new NoItemsException(...);
this.SetStatus(OrderStatus.Active);
.....
}
}
Repositories (Data Access Layer):
public class OrderRepository : IOrderRepository
{
public PurchaseOrder GetById(int id)
{
// data access code to access ORM or any data access framework.
}
}
Infrastrucute:
public class Logger : ILogger
{
public void Exception(Exception ex)
{
// write exception to whatever
}
}
I'm brand new to OData and WCF data services so this might be an easy problem. I'm using VS Web Developer Express 2010 where I have a very simple WCF Data Service hosted in a console app. It's returning an IQuerable collection of a simple 'Study' class from a repository (located in a separated dll project), which in turn retrieves 'Study' classes from a db project in another dll (so 3 projects in the solution).
I also have an 'Experiment' class in the db project and there can be multiple Experiments in a Study. When I exclude the Experiment class from the Study everything works and I get data coming back. The problem happens when I add a List collection to the Study class, then I get a runtime error when I try to run the service. In Firebug the error is '500 Internal Server Error', and the message in the browser is 'Request Error. The server encountered an error processing the request. See server logs for more details.'
I have IIS 7 and I also just installed IIS 7.5 but again it's brand new to me, so I can't figure out where the service is hosted or where to view the server / web logs. There are only IIS 7 logs visible in 'C:\inetpub\logs\LogFiles\W3SVC1'. The VS web server (Cassini) doesn't start when I run the app, so this suggests it's being hosted in IIS 7.5 (?).
So
- how do I return child classes / complex objects?
- how do I know where my service is hosted and where can I find the server logs?
Here's the host app:
using MyStudyRepository;
using MyStudyDB;
namespace MyStudyService
{
public class Program
{
public static void Main(string[] args)
{
string serviceAddress = "http://localhost:998";
Uri[] uriArray = { new Uri(serviceAddress) };
Type serviceType = typeof(StudyDataService);
using (var host = new DataServiceHost(serviceType,uriArray))
{
host.Open();
Console.WriteLine("Press any key to stop service");
Console.ReadKey();
}
}
}
public class StudyDataService : DataService<StudyRepository>
{
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
}
}
}
Here's the repository:
using MyStudyDB;
namespace MyStudyRepository
{
public class StudyRepository
{
List<Study> _List = new List<Study>();
//Add constructor to populate myStudies list on creation of class
public StudyRepository()
{
for (int i = 1; i < 5; i++)
{
Study myStudy = new Study() { ID = i, StudyOwnerId = i, StudyName = "Study" + i.ToString() /*, Experiments = null */ };
_List.Add(myStudy);
}
}
public IQueryable<Study> Studies
{
get
{
return _List.AsQueryable<Study>();
}
}
}
}
And here's the DB:
namespace MyStudyDB
{
public class Study
{
public int ID { get; set;}
public int StudyOwnerId { get; set; }
public string StudyName { get; set; }
//public List<Experiment> Experiments { get; set; }
}
public class Experiment
{
public int ID { get; set; }
public string Name { get; set; }
public int StudyId { get; set; }
}
}
To debug the WCF Data Service please refer to this blog post: http://blogs.msdn.com/b/phaniraj/archive/2008/06/18/debugging-ado-net-data-services.aspx
As to why the collection of Experiment doesn't work, there are two reasons:
The Experiment class is not recognized as an entity type because there's no entity set for it. (Entity set is the IQueryable property on your repository class, which you don't have). As a result the Experiment class is only recognized as a complex type.
The currently released version of WCF Data Services doesn't support MultiValues, MultiValue is effectively a collection of primitive or complex types.
So you have two way to "fix" this. Either make sure that Experiment is in fact an entity, by adding IQueryable property on your repository class.
Or use the latest CTP (http://blogs.msdn.com/b/astoriateam/archive/2011/06/30/announcing-wcf-data-services-june-2011-ctp-for-net4-amp-sl4.aspx) which does support MultiValues.
Thanks! And I guess it is missing the DataServiceKey attribute on the class as follows:
[DataServiceKey("ID")]
public class Study
{
.....
}
I want to return an anonymous type over WCF. Is this possible?
You cannot use anonymous types, but maybe you are talking about WCF and untyped messages?
There is an option in WCF to just define a parameter of type Message (and possibly a return value of the same type). This is just the raw message that goes to WCF (and comes back from it).
I can't find much good information out there - there's some documentation on MSDN, but the best I've seen so far is Kurt Claeys' blog post WCF : Untyped messages on WCF operations.
I would not recommend using this approach - it's a lot more grunt work to handle the message contents directly yourself and that's what WCF is trying to spare us from - but if you absolutely, positively have to tweak every bit of your message - this seems like the way to go.
Marc
You can't return an anonymous type from any method, can you? So why would you be able to return it from WCF?
Looks like you cannot do so with the XML Serializer because of some complaint about a parameterless constructor but it works for the json serializer if you are serving to an ajax client as indicated by Dave Ward.
OK, I understand. But then if I define
a type - MyObj - for this purpose and
mark its members IsRequired=false, how
can I create+send across an instance
of MyObj with only some of its
members? Is this possible??
Take a look at [DataMember(EmitDefaultValue=false)]
No, it is not. You'll have to define your types ahead of time.
You definitely can return anonymous types. This works, for example:
public object GetLatestPost()
{
XDocument feedXML = XDocument.Load("http://feeds.encosia.com/Encosia");
var posts = from feed in feedXML.Descendants("item")
select new
{
Title = feed.Element("title").Value,
Link = feed.Element("link").Value,
Description = feed.Element("description").Value
};
return posts.First();
}
If you call that method as an ASMX ScriptService's WebMethod, you'll get this JSON from it:
{"d":
{"Title":"Using an iPhone with the Visual Studio development server",
"Link":"http://feeds.encosia.com/~r/Encosia/~3/vQoxmC6lOYk/",
"Description":" Developing iPhone-optimized portions of an ASP.NET ..."}}
You can use a return type of IEnumerable to return a collection of anonymous types also.
You can use the ExpandoObject. When you define a property in a DTO as ExpandoObject the client is generated as Dictionary:
Contract DTO
public class TaskDTO
{
public string Type { get; set; }
public ExpandoObject Args { get; set; }
public string Id { get; set; }
public TaskDTO SuccessTask { get; set; }
public TaskDTO FailTask { get; set; }
public bool IsFinal { get; set; }
}
Client
using (var client = new JobServiceClient())
{
var task = new TaskDTO
{
Id = Guid.NewGuid().ToString(),
Type = "SendEmailTask",
IsFinal = true
};
dynamic args = new ExpandoObject();
args.To = "who#mail.com";
args.Title = "test job service";
args.Content = "test job service";
task.Args = ((IDictionary<string, object>)args).ToDictionary(i => i.Key, i => i.Value);
client.Execute(task);
}
Service
dynamic args = dto.Args;
I was looking at the differences between POCO and DTO (It appears that POCO's are dto's with behaviour (methods?))and came across this article by Martin Fowler on the anaemic domain model.
Through lack of understanding, I think I have created one of these anaemic domain models.
In one of my applications I have my business domain entities defined in a 'dto' dll. They have a lot of properties with getter's and setter's and not much else. My business logic code (populate, calculate) is in another 'bll' dll, and my data access code is in a 'dal' dll. 'Best practice' I thought.
So typically I create a dto like so:
dto.BusinessObject bo = new dto.BusinessObject(...)
and pass it to the bll layer like so:
bll.BusinessObject.Populate(bo);
which in turn, performs some logic and passes it to the dal layer like so:
dal.BusinessObject.Populate(bo);
From my understanding, to make my dto's into POCO's I need to make the business logic and behaviour (methods) part of the object. So instead of the code above it is more like:
poco.BusinessObject bo = new poco.BusinessObject(...)
bo.Populate();
ie. I am calling the method on the object rather than passing the object to the method.
My question is - how can I do this and still retain the 'best practice' layering of concerns (separate dll's etc...). Doesn't calling the method on the object mean that the method must be defined in the object?
Please help my confusion.
Typically, you don't want to introduce persistence into your domain objects, since it is not part of that business model (an airplane does not construct itself, it flies passengers/cargo from one location to another). You should use the repository pattern, an ORM framework, or some other data access pattern to manage the persistent storage and retreival of an object's state.
Where the anemic domain model comes in to play is when you're doing things like this:
IAirplaneService service = ...;
Airplane plane = ...;
service.FlyAirplaneToAirport(plane, "IAD");
In this case, the management of the airplane's state (whether it's flying, where it's at, what's the departure time/airport, what's the arrival time/airport, what's the flight plan, etc) is delegated to something external to the plane... the AirplaneService instance.
A POCO way of implementing this would be to design your interface this way:
Airplane plane = ...;
plane.FlyToAirport("IAD");
This is more discoverable, since developers know where to look to make an airplane fly (just tell the airplane to do it). It also allows you to ensure that state is only managed internally. You can then make things like current location read-only, and ensure that it's only changed in one place. With an anemic domain object, since state is set externally, discovering where state is changed becomes increasingly difficult as the scale of your domain increases.
I think the best way to clarify this is by definition:
DTO: Data Transfer Objects:
They only serve for data transportation typically between presentation layer and service layer. Nothing less or more. Generally it is implemented as class with gets and sets.
public class ClientDTO
{
public long Id {get;set;}
public string Name {get;set;}
}
BO: Business Objects:
Business objects represents the business elements and naturally the best practice says they should contain business logic also. As said by Michael Meadows, it is also good practice to isolate data access from this objects.
public class Client
{
private long _id;
public long Id
{
get { return _id; }
protected set { _id = value; }
}
protected Client() { }
public Client(string name)
{
this.Name = name;
}
private string _name;
public string Name
{
get { return _name; }
set
{ // Notice that there is business logic inside (name existence checking)
// Persistence is isolated through the IClientDAO interface and a factory
IClientDAO clientDAO = DAOFactory.Instance.Get<IClientDAO>();
if (clientDAO.ExistsClientByName(value))
{
throw new ApplicationException("Another client with same name exists.");
}
_name = value;
}
}
public void CheckIfCanBeRemoved()
{
// Check if there are sales associated to client
if ( DAOFactory.Instance.GetDAO<ISaleDAO>().ExistsSalesFor(this) )
{
string msg = "Client can not be removed, there are sales associated to him/her.";
throw new ApplicationException(msg);
}
}
}
Service or Application Class
These classes represent the interaction between User and the System and they will make use of both ClientDTO and Client.
public class ClientRegistration
{
public void Insert(ClientDTO dto)
{
Client client = new Client(dto.Id,dto.Name); /// <-- Business logic inside the constructor
DAOFactory.Instance.Save(client);
}
public void Modify(ClientDTO dto)
{
Client client = DAOFactory.Instance.Get<Client>(dto.Id);
client.Name = dto.Name; // <--- Business logic inside the Name property
DAOFactory.Instance.Save(client);
}
public void Remove(ClientDTO dto)
{
Client client = DAOFactory.Instance.Get<Client>(dto.Id);
client.CheckIfCanBeRemoved() // <--- Business logic here
DAOFactory.Instance.Remove(client);
}
public ClientDTO Retrieve(string name)
{
Client client = DAOFactory.Instance.Get<IClientDAO>().FindByName(name);
if (client == null) { throw new ApplicationException("Client not found."); }
ClientDTO dto = new ClientDTO()
{
Id = client.Id,
Name = client.Name
}
}
}
Personally I don't find those Anaemic Domain Models so bad; I really like the idea of having domain objects that represent only data, not behaviour. I think the major downside with this approach is discoverability of the code; you need to know which actions that are available to use them. One way to get around that and still keep the behaviour code decoupled from the model is to introduce interfaces for the behaviour:
interface ISomeDomainObjectBehaviour
{
SomeDomainObject Get(int Id);
void Save(SomeDomainObject data);
void Delete(int Id);
}
class SomeDomainObjectSqlBehaviour : ISomeDomainObjectBehaviour
{
SomeDomainObject ISomeDomainObjectBehaviour.Get(int Id)
{
// code to get object from database
}
void ISomeDomainObjectBehaviour.Save(SomeDomainObject data)
{
// code to store object in database
}
void ISomeDomainObjectBehaviour.Delete(int Id)
{
// code to remove object from database
}
}
class SomeDomainObject
{
private ISomeDomainObjectBehaviour _behaviour = null;
public SomeDomainObject(ISomeDomainObjectBehaviour behaviour)
{
}
public int Id { get; set; }
public string Name { get; set; }
public int Size { get; set; }
public void Save()
{
if (_behaviour != null)
{
_behaviour.Save(this);
}
}
// add methods for getting, deleting, ...
}
That way you can keep the behaviour implementation separated from the model. The use of interface implementations that are injected into the model also makes the code rather easy to test, since you can easily mock the behaviour.