Я постараюсь дать вам некоторые рекомендации.
Предположим, что у вас есть существующая служба WCF для продуктов, которая определена следующим образом (нас не волнует реализация, на данный момент это не важно, вы можете реализовать ее по своему желанию, в отличие от жестко заданных значений, проходя через база данных SQL и ORM для использования другой службы в облаке):
[DataContract]
public class Product
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}
[ServiceContract]
public interface IProductsService
{
[OperationContract]
Product Get(int id);
}
Теперь в вашем приложении ASP.NET MVC первый шаг - добавить ссылку на службу, указав на WSDL. Это сгенерирует прокси клиентские классы.
Затем вы можете добавить пакет Unity.Mvc3
NuGet в ваше приложение MVC
Тогда в вашем Application_Start
вы можете сконфигурировать контейнер (очевидно, эта конфигурация может быть выведена в отдельный метод, чтобы не загромождать ваш Global.asax им):
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var container = new UnityContainer();
container
.RegisterType<IProductsService, ProductsServiceClient>()
.Configure<InjectedMembers>()
.ConfigureInjectionFor<ProductsServiceClient>(new InjectionConstructor("*"));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
IProductsService
и ProducsServiceClient
, используемые в этой конфигурации, являются прокси-классами, генерируемыми при импорте определения веб-службы.
Отныне вещи становятся тривиальными:
public class HomeController : Controller
{
private readonly IProductsService _productsService;
public HomeController(IProductsService productsService)
{
_productsService = productsService;
}
public ActionResult Index()
{
var product = _productsService.Get(1);
return View(product);
}
}
и некоторые соответствующие индексные представления:
@model Product
<div>
@Html.DisplayFor(x => x.Name)
</div>
Как видно из этого примера, благодаря абстракции IProductsService
, HomeController полностью отделен от любых конкретных реализаций службы. В Today в вашем Global.asax вы решили использовать WCF (ProductsServiceClient), но завтра вы можете решить использовать совсем другую реализацию. С помощью одного изменения конфигурации вашего DI-контейнера вы можете переключить реализацию. Благодаря этой слабой связи, ваши контроллеры могут быть полностью проверены модулем изолированно.
Здесь важно понимать, что ваш бизнес - это класс Product и интерфейс IProductsService
. Это то, что отражает ваш домен. Это М в MVC. Реализации могут измениться, но это должно остаться без изменений, в противном случае вы ошибочно определили свои бизнес-требования, которые могут иметь катастрофические последствия в долгосрочной перспективе.
Примечание: одна вещь, которую я не рассмотрел в этом примере и которая очень важна, - это использование моделей представлений. В правильно спроектированном приложении ASP.NET MVC вы никогда не должны передавать доменные модели своим представлениям (в этом примере класс Product). Вы должны использовать просмотр моделей. Модели представлений - это классы, специально разработанные для требований данного представления. Таким образом, в реальном приложении ASP.NET MVC у вас будет класс ProductViewModel, которому будет сопоставлена модель домена Product в действии контроллера, и именно эта ProductViewModel будет передана в представление. Эти модели представлений должны быть определены в проекте MVC, так как, в отличие от ваших моделей предметной области, они не могут быть использованы повторно и отражают только конкретные требования одного представления. Чтобы упростить сопоставление между моделями доменов и моделями представления, вы можете взглянуть на AutoMapper .