ASP.NET MVC 条件 ViewModel 抽象
Posted
技术标签:
【中文标题】ASP.NET MVC 条件 ViewModel 抽象【英文标题】:ASP.NET MVC Conditional ViewModel Abstraction 【发布时间】:2013-07-19 15:04:33 【问题描述】:我是 ASP.NET MVC 的新手,我被困在一个点上。我在一个机密网站上工作。我的情况是,我有很多类别,用户可以在其中发布他们的广告,并且每个广告类别都有不同的视图。我创建了一个控制器动作,如
public ActionResult PostAd(string CategoryName, string SubCategoryName)
if(categoryName == "Vehicle" && SubCategoryName == "Cars")
var model = new CarAdViewModel();
// set CarAdViewModel properties...
return View("CarAdCreateView", model);
else if(categoryName == "Vehicle" && SubCategoryName == "Bikes")
var model = new BikeAdViewModel();
// set BikeAdViewModel properties...
return View("BikeAdViewModel", model);
else if(categoryName == "Property" && SubCategoryName == "RentHouse")
var model = new RentHouseAdViewModel();
// set RentHouseAdViewModel properties...
return View("RentHouseAdViewModel", model);
else................... so on and so on
我的问题是我有近 60 多个类别和子类别。如果我继续像上面那样为 60 多个类别和子类别编码,我的 PostAd
方法将会爆炸并变得难以管理。
请告诉我一些可以让我摆脱这个问题的最佳实践或模式。
【问题讨论】:
您确定需要为每个类别提供不同的视图吗?你为什么这么认为? @MystereMan 我所有的广告字段都不同,比如 CarAd 有:BodyType、Make、Model、MechanicalCondition 等,而 RentHouse 有:NumberOfRooms、NumberofBathroom、IsFurnished、HasAttachedBath 等等。告诉我有没有其他方法? 视图和操作方法需要根据其逻辑进行更改,不一定根据数据或字段进行更改。您可以根据集合类型在视图中呈现不同的字段。您应该查看 EditorTemplates coding-in.net/asp-net-mvc-3-how-to-use-editortemplates @MystereMan 很漂亮,但是它将如何解决我的问题?我有很多基于类别和子类别的 ViewModel。 @MystereMan 我认为这不会让我的生活变得不那么悲惨,因为现在我必须创建不同的 EditorTemplates 而不是不同的 Views。我认为这是相同数量的代码。部分视图也可以这样工作。 【参考方案1】:不幸的是,您正在做的一些事情是无法避免的。需要有某种形式的基于类别的模型和视图选择。
使用工厂模式。创建一个基类:
public abstract class BaseCategory
public abstract string GetViewName();
public abstract Object CreateModelFromFormData();
对于每个类别,创建一个从BaseCategory
派生的子类并实现抽象函数。
在您的操作中,请执行以下操作:
public ActionResult PostAd(string categoryName, string subCategoryName)
BaseFactory factory;
if (categoryName == "Vehicle")
if (subCategoryName == "Cars")
factory = new CarsFactory();
else ...
else ...
return View(factory.GetViewName(), factory.CreateModelFromFormData());
我对这个架构有几个原因:
我有意使用if/else
进行工厂选择。将为每个操作调用创建和重新创建您的控制器。因此,预先填充列表将不断且不必要地为不会被选择的类别创建对象。一个简单的if/else
会更有效率。如果你想阻止if/else
,你可以把你的工厂放在Dictionary
中,然后根据类别进行选择,但这会是很多不必要的构造函数。
我将CreateModelFromFormData
设为一个函数,因为我假设您需要从已发布的表单数据中复制数据。这可能需要传入数据,但我让函数无参数。
我使用基类/派生类,因为表单数据的复制可能需要根据正在创建的模型和正在发布的表单数据进行自定义。此外,保存到持久存储(文件或数据库)也可能是特定于类别的。
【讨论】:
【参考方案2】:这将是一些可能的解决方案之一
public class PostAdData
public string CategoryName;
public string SubCategoryName;
public string ViewName;
public Type Model;
public class PostController : Controller
private readonly List<PostAdData> _theData;
public HomeController()
_theData = InitializeData();
public ActionResult PostAd(string categoryName, string subCategoryName)
var data = _theData.FirstOrDefault(c => c.CategoryName == categoryName && c.SubCategoryName == subCategoryName);
if (data != null)
var model = Activator.CreateInstance(data.Model);
return View(data.ViewName, model);
return View("Error");
[NonAction]
public List<PostAdData> InitializeData()
var result = new List<PostAdData>
new PostAdData
CategoryName = "Vehicle",
SubCategoryName = "Cars",
ViewName = "CarAdCreateView",
Model = typeof (CarAdViewModel)
;
return result;
【讨论】:
将您的_theData
设为静态并填充到静态构造函数中。否则,它将为每个操作调用填充并重新填充。【参考方案3】:
您应该让这些数据成为驱动力。您创建一个具有类别和子类别的复合主键的查找表。然后它有一个带有 View 的表。然后,您只需为每个类别/子类别/视图组合添加行。
如果您绝对不想要数据库,那么您可以使用简单的哈希集或字典。
var views = new Dictionary<Tuple<string,string>,string>();
views.Add(new Tuple<string,string>("Vehicle", "Cars"), "CarAdCreateView");
然后,您只需在您的 PostAd 中查找正确的视图。
【讨论】:
我更喜欢数据库方法,但我不知道该怎么办。【参考方案4】:www.asp.net 上我的问题的解决方案真是太棒了,这是链接:http://forums.asp.net/t/1923868.aspx/1?ASP+NET+MVC+Conditional+ViewModel+Abstraction
编辑:
我的代码是:
public class AdsController : Controller
private readonly IAdService _adService;
public AdsController(IAdService adService)
_adService = adService;
public ActionResult PostAd(string Category, string SubCategory)
//Here I will call
var strategy = GetStrategy(CategoryName, SubCategoryName);
strategy.FillModel(_adService );
return View(strategy.ViewName, strategy.Model);
【讨论】:
这种方法的问题是它会在每次动作调用时创建对象以寻找合适的类。事实上,我怀疑性能会比@abbas-amiri 的方法更差,因为它会执行额外的“搜索类”。是的,它很漂亮,但你会因此而受到打击。如果您打算继续使用此解决方案,那么至少“发现”一次类并缓存它们。 我知道使用 GetStrategy() 方法会损失一些性能,但为什么它会在每次操作调用时创建这些对象? 作为GetStrategy
的一部分,隐藏在LINQ 语句中的是Activator.CreateInstance
,它将创建它找到的对象的一个实例,然后将您想要的类别与该对象中包含的类别进行比较。这些对象被创建,比较然后销毁(如果它不是正确的)。您为每个PostAd
调用调用GetStrategy
,因此它将为每个PostAd
创建、比较和销毁许多对象。
好的,我明白了。谢谢:)以上是关于ASP.NET MVC 条件 ViewModel 抽象的主要内容,如果未能解决你的问题,请参考以下文章
ASP .Net MVC 模型 - ViewModel - 视图
Asp.net Core 如何将 ReflectionIT.Mvc.Paging 与 ViewModel 一起使用?
ASP.NET MVC 架构:ViewModel 通过组合、继承还是复制?
ASP.NET MVC:让 ViewModel 进入 ViewPage 的部分视图