Как настроить службу DAL RESTful с помощью EFCodeFirst для приложений MVC?

Для приложения MVC3 я хочу создать повторно используемый DAL, доступ к которому осуществляется как к службе, поскольку в будущем он будет использоваться для других проектов.

Я создал все объекты с помощью шаблонов 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, и мне не ясно, как подключить модели к моему сервису, и мне нужно какое-то направление для этого.

Спасибо.


person ElHaix    schedule 23.03.2012    source источник


Ответы (2)


Предположим, вы хотите предоставить объект с именем 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. Служба отдыха WCF автоматически возвращает XML, если тип содержимого — «text/xml», и JSON, если это «application/json».

Обратите внимание, что приложение MVC ничего не знает о базе данных, объектах базы данных или ее контексте базы данных. На самом деле в приложении MVC нет логики базы данных. Вам придется уделить пристальное внимание безопасности, потому что пользовательский контекст отсутствует в оставшихся службах WCF. Но это уже совсем другое обсуждение.

person bloudraak    schedule 24.03.2012
comment
Это подтверждает то, что я обнаружил на прошлой неделе, поскольку это может быть не лучший подход. При использовании шаблона WCF RESTful вы вынуждены добавлять дополнительный код для сериализации данных, даже если это чисто приложение .Net. Позже я понял, что никогда не хочу давать прямой доступ со стороны клиента (каким-либо образом) к DAL. Однако в будущих проектах может потребоваться такая гибкость. Отличное объяснение процесса сериализации. Спасибо. - person ElHaix; 26.03.2012
comment
Вы можете использовать WCF для автоматического выполнения всей сериализации и т. д., как описано в в этом примере. Однако вы теряете много возможностей на клиенте, особенно когда дело доходит до обработки ошибок. - person bloudraak; 26.03.2012

Можно думать об этом так, что ваше приложение MVC теперь знает только о вашем сервисе. Он понятия не имеет, что за этим стоит DAL. По сути, считайте службу своим уровнем «Постоянство». Итак, теперь ваша модель MVC должна заполнить себя с помощью сервиса. Таким образом, точно так же, как любое другое приложение будет заполнять сервис, ваша модель будет заполнять себя сама. Затем ваши контроллеры будут использовать вашу модель, возвращающую ваши представления.

Это было не то, что вы, возможно, искали, но существует множество ресурсов о том, как использовать службы RESTful в .NET. Проверьте их и получите те, которые заполняют вашу модель. Затем получите свою модель для просмотра.

person Quickhorn    schedule 23.03.2012
comment
Я только что перечитал ваш пост и понял, что вам не хватает интерфейса для созданного вами сервиса. Это должно быть суть вашего вопроса. Я по-прежнему считаю, что вам нужно сосредоточиться на части вашего вопроса, касающейся моей модели, а не на части MVC вашего вопроса. - person Quickhorn; 23.03.2012