Ответ 1
1. Разделение проблем
SoC в MVC - это не разделение бизнес-логики с пользовательским интерфейсом. Что еще более важно, он дает основные функции контроллера:
- чтобы заполнить модель модели из модели домена;
- для просмотра активности вида;
- для отображения представлений в зависимости от логики домена.
Вид отвечает только за представление данных в MVC.
Это делает тестирование очень простым, поскольку контроллер работает с чистыми классами Model Model, в отличие от WebForms, который управляет событиями и формой.
В WebForms View обрабатывается вся активность пользовательского интерфейса и в основном принимает решения о потоке сценариев.
Здесь я хотел бы упомянуть, что термины Показать модель и Модель домена разные. Модель домена - это термин, описывающий все сервисы, бизнес-логику и DAL, скрытые от контроллера с некоторым фасадом. Модель View - это класс, который инкапсулирует данные, необходимые для просмотра. Он может совместно использоваться моделью домена в простых случаях. Почему два класса?
Вот аналогичные фрагменты кода ASP.NET MVC и WebForms, выполняющие одни и те же вещи: 1) получение данных 2) обработка данных. В обоих случаях я предполагаю, что IDomainModel
вводится.
MVC:
public class SomeController : Controller
{
// injected
public IDomainModel Domain { get; set; }
public ViewResult Edit()
{
var record = Domain.GetRecord(1);
var dictionary = Domain.GetSomeDictionary();
var model = new SomeViewModel(record, dictionary);
return View(model);
}
[HttpPost]
public ActionResult Edit(SomeViewModel model)
{
if (ModelState.IsValid)
// save
return RedirectToAction("Result");
else
return View(model);
}
}
WebForms:
public partial class SomePage : System.Web.UI.Page
{
// injected
public IDomainModel Domain { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
var record = Domain.GetRecord(1);
var dictionary = Domain.GetSomeDictionary();
RecordId.Text = record.Id.ToString();
RecordName.Text = record.Name;
RecordDescription.Text = record.Description;
DicValue.DataSource = dictionary;
DicValue.DataValueField = "Id";
DicValue.DataTextField = "Value";
DicValue.SelectedValue = record.DictionaryEntryId.ToString();
DicValue.DataBind();
}
protected void btnSave_Click(object sender, EventArgs e)
{
var record = new RecordModel
{
Id = Int32.Parse(this.RecordId.Text),
Name = this.RecordName.Text,
Description = this.RecordDescription.Text,
DictionaryEntryId = Int32.Parse(this.DicValue.Text)
};
// save
}
}
Тестирование MVC-контроллера Edit
GET невероятно прост:
[TestMethod]
public void EditGetTest()
{
SomeController target = new SomeController();
var record = new RecordModel { Id = 1, Name = "name1", Description = "desc1", DictionaryEntryId = 1 };
var dictionary = new List<SomeDictionaryEntry>
{
new SomeDictionaryEntry { Id = 1, Value = "test" }
};
target.Domain = new SimpleMVCApp.Models.Fakes.StubIDomainModel()
{
GetRecordInt32 = (id) => { return record; },
GetSomeDictionary = () => { return dictionary; }
};
var result = target.Edit();
var actualModel = (SomeViewModel)result.Model;
Assert.AreEqual(1, actualModel.Id);
Assert.AreEqual("name1", actualModel.Name);
Assert.AreEqual("desc1", actualModel.Description);
Assert.AreEqual(1, actualModel.DictionaryEntryId);
}
Чтобы протестировать события WebForms, нам нужно сделать много изменений и допущений: нам нужно сделать методы общедоступными, нам нужно инициализировать форму и ее элементы управления. Это приводит к тяжелому анализу, который невозможно для 3) TDD.
2. Включить полный контроль над отображаемым HTML
Я думаю, что это утверждение немного преувеличено. Только HTML может полностью контролировать отображаемый HTML. Что касается HtmlHelpers, DisplayTemplates и EditorTemplates, хотя команда сделала значительные улучшения в 6 версиях фреймворка, все равно иногда раздражает преобразование дополнительныхViewData в атрибуты html.
Например, чтобы передать некоторые html-атрибуты на вход, вы не можете использовать @Html.EditorFor
, вам нужно будет использовать @Html.TextBoxFor
.
В то же время в ASP.NET вы можете указать любые атрибуты для любых элементов, и они просто будут отображаться.
MVC:
Неправильно:
@Html.EditorFor(m => m.Name, new { MySuperCustomAttribute = "Hello" })
Правильно:
@Html.TextBoxFor(m => m.Name, new { MySuperCustomAttribute = "Hello" })
ASP.NET:
<asp:TextBox runat="server" ID="RecordName" MySuperCustomAttribute="hello"></asp:TextBox>
3. Включить тестовое развитие (TDD)
Я думаю, что это утверждение относится к тестированию Controller vs Code-Behind. Я рассмотрел это в 1.
4. Нет событий ViewState и PostBack
ViewBag и ViewData являются слабоспециализированными средствами для передачи данных между контроллером и представлениями. Они отображаются как элементы, ничего похожего на ViewState. Например, в моем представлении я инициализируется ViewBag.Title = "EditView";
, который позволяет мне использовать эту строку на странице макета: <title>@ViewBag.Title - My ASP.NET MVC Application</title>
. На странице это выглядит так: <title>EditView - My ASP.NET MVC Application</title>
Что касается TempData, Session и Application, они хранятся на стороне сервера. Это не отображается на странице.
5. Легкая интеграция с JQuery
Я не вижу, как упрощение интеграции с JQuery для MVC. Вот как мы интегрируем JQuery в WebForms:
<script src="Scripts/jquery-1.8.2.min.js"></script>
<script>
$(document).ready(function () {
$('#DicValue').change(function () {
$('#ChosenValue').text($('#DicValue option:selected').val());
});
});
</script>
И вот почти такой же фрагмент для ASP.NET MVC:
@section scripts{
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script>
$(document).ready(function () {
$('#DictionaryEntryId').change(function () {
$('#ChosenValue').text($('#DictionaryEntryId option:selected').val());
});
});
</script>
}
Здесь есть еще один момент, чтобы упомянуть о JQuery: поскольку ASP.NET MVC является довольно мнимой структурой, он становится несколько ограничивающим для широкого использования JS. Он был первоначально разработан для разработки на основе шаблонов Scaffold, и с ним лучше всего. JQuery хорош для запросов ajax и для некоторой незначительной логики в ASP.NET MVC, но когда вы начнете широко использовать его, вы получите два контроллера для каждого представления: С# один и JS. Привет, Unit Testing! Также JQuery (UI) очень хорош с его богатым набором элементов управления пользовательского интерфейса.
ASP.NET разработан с учетом обратной связи, и они диктуют вам базовую модель приложения. Тем не менее, для ASP.NET существуют различные инструменты пользовательского интерфейса для повышения динамичности приложения, и все еще есть место для JQuery.
Ничего себе, это был длинный ответ. Надеюсь, это поможет.