如何使用EFCodeFirst为MVC应用程序设置DAL RESTful服务?

时间:2012-03-23 15:44:02

标签: asp.net-mvc-3 model asp.net-4.0 data-access-layer wcf-rest

对于MVC3应用程序,我想创建一个可以作为服务访问的可重用DAL,因为这将在未来用于其他项目。

created all the entities将TT模板和EFCodeFirst放在一个单独的项目中,然后在RESTful WCF服务中使用它。

这个服务的结构与我编写的其他WCF服务有点不同,我在服务接口中指定了RESTful签名和可选的JSON响应作为方法装饰器,即:

    [WebGet(UriTemplate = "GetCollection")]
    public List<SampleItem> GetCollection()
    {
        // TODO: Replace the current implementation to return a collection of SampleItem instances
        return new List<SampleItem>() { new SampleItem() { Id = 1, StringValue = "Hello" } };
    }

    [WebInvoke(UriTemplate = "", Method = "POST")]
    public SampleItem Create(SampleItem instance)
    {
        // TODO: Add the new instance of SampleItem to the collection
        throw new NotImplementedException();
    }

这个RESTful WCF服务(从RESTful WCF选项创建)不同的地方是没有接口,我可以用我需要的东西来装饰服务方法 - 没关系。该服务将公开GetUserByID(int id)等方法。

问题是我想在MVC3应用程序中使用它,并且不清楚如何将模型连接到我的服务,并希望有一些方向来实现这一点。

感谢。

2 个答案:

答案 0 :(得分:0)

考虑这一点的方法是,您的MVC应用程序现在只知道您的服务。它不知道背后有DAL。基本上,将服务视为“持久性”层。所以,现在你的MVC模型必须使用该服务填充自己。因此,就像任何其他应用程序将填充服务一样,这就是您的模型将如何填充自己。然后您的控制器将使用您的模型返回您的视图。

这不是你可能正在寻找的细节,但是有很多关于如何在.NET中使用RESTful服务的资源。检查那些,并让那些填充你的模型。然后让你的模型进入你的视野。

答案 1 :(得分:0)

假设您要公开名为Person的实体。 WCF REST服务可能如下所示:

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]    
public partial class PeopleWebService
{
    [WebGet(UriTemplate = "")]
    public List<Person> GetCollection()
    {
        try
        {
            IPeopleRepository repository = ServiceLocator.GetInstance<IPeopleRepository>();
            var people = repository.GetPeople();
            // use automapper to map entities to Person resource
            var result = Mapper.Map<List<Person>>(people);
            return result;
        }
        catch (Exception exception)
        {
            // do logging etc
            throw new WebFaultException(HttpStatusCode.InternalError);
        }
    }

    /* other methods */
}

这些服务也可以由T4生成。

请注意,WCF服务本身不需要接口。我通常不直接在WCF服务中公开任何数据库实体,因为我的服务演变与我的数据库实体不同。一旦API发布,它应该几乎保持不变。这可以防止我更改我的数据库架构以适应新的要求。

相反,我将我的实体映射到资源。所以Person可能如下所示:

[DataContract]
public class Person
{
    [DataMember]
    public string GivenName { get; set; }

    / * more properties */
}

使用T4生成这些也可能是一件好事。路由定义如下:

public void Register(RouteCollection routes)
{
    routes.AddService<WorkspaceWebService>("api/v1/people");
}

要从ASP.NET MVC项目中使用它,您可以将上面定义的资源(也称为Person)作为程序集共享,或者您可以使用T4生成几乎相同的单独资源集,但是ASP.NET MVC所需的一些其他属性,如用于验证的属性。我会生成它,因为我的ASP.NET MVC视图模型通常独立地发展到我的REST资源。

假设您的REST服务在https://api.example.com/运行,而您的MVC网站在https://www.example.com/运行。您的PeopleController可能如下所示。

public class PeopleController : ControllerBase
{
    [HttpGet]
    public ActionResult Index()
    {
        return View(Get<List<Person>>(new Uri("https://api.example.com/api/v1/people")));
    }

    protected T Get<T>(Uri uri)
    {
        var request = (HttpWebRequest) WebRequest.Create(uri);
        request.Method = "GET";
        request.ContentType = "text/xml";
        using (var response = (HttpWebResponse) request.GetResponse())
        {
            using (var responseStream = response.GetResponseStream())
            {
                Debug.Assert(responseStream != null, "responseStream != null");
                var serializer = new DataContractSerializer(typeof (T));
                return (T) serializer.ReadObject(responseStream);
            }
        }
    }
}

根据您的问题,我假设您要使用JSON。为此,您只需在请求上设置适当的ContentType并使用DataContractJsonSerializer而不是DataContractSeralizer。请注意,日期和DataContractJsonSerializer存在一些问题。如果contenttype是“text / xml”,WCF rest服务将自动返回XML,如果是“application / json”,则自动返回JSON。

请注意,MVC应用程序不了解数据库,数据库实体或其数据库上下文。事实上,MVC应用程序中没有数据库逻辑。您必须密切关注安全性,因为WCF休息服务中缺少用户上下文。但是,这是一个完全不同的讨论。