允许操作和视图和模型中的高度变化

时间:2009-10-16 20:39:37

标签: asp.net-mvc architecture

我正在设计一个产品管理系统。我想知道在我的应用程序中处理每个Action / View中的大量变化的最佳方法。该应用程序处理20个类别和12个目标市场,每个类别都会影响每个产品需要收集的数据。例如,“QuickAdd”操作接收核心数据,如产品名称和SKU,以及基于产品添加到的类别和目标市场的组合的一些其他关键信息(下面的示例)。类别和目标市场不是产品的可配置属性,使用该系统的用户只能在特定组合下工作,例如Toys / USA。提到这一点的原因是我无法将表单设计为具有每个Category / Market组合的属性部分,它需要工作就像表单仅针对该类别/市场 - 用户不了解其他组合。

希望澄清可能情况的一些例子:

  

如果我要将产品添加到类别中   我需要的目标市场美国玩具   要求“年龄范围”和“没有   它通过了安全检查“。

     

如果我要将产品添加到类别中   玩具与目标市场墨西哥,我只是   需要问“年龄范围”。

     

如果我要添加产品   类别服装与目标   市场美国我需要要求   “风格”和“材料”

     

如果我要添加产品   类别服装与目标   加拿大市场我需要要求   “风格”,“材料”和“美国价格”

     

我们有20个类别和12个目标   市场,加上有10种形式   需要以这种方式表现,所以   理论上有2400个不同   动作/查看/模型

所以问题是,在ASP.NET MVC中,处理显示所有这些动态表单和处理发送到操作的数据变体的最佳方法是什么?

修改
澄清如何确定产品的属性:它们基于属于市场中类别的产品的层次结构。例如,它不是我们要求的所有玩具属性和美国属性的添加,它是在美国市场上销售的玩具产品的属性。在美国销售的玩具需要“安全检查”信息,但美国的服装不需要。墨西哥的玩具也不需要“安全检查”信息,因此该属性并非所有Toys或所有美国产品所固有,而是属于类别和市场的组合。

4 个答案:

答案 0 :(得分:2)

我会为属性类型创建一些域模型。

public enum AttributeTypeEnum
{
    Currency,
    Range,
    List,
    Number,
    Text,
    Boolean
}

public interface class IAttribute
{
    int Id { get; set; }
    string Name { get; set; } 
    AttributeTypeEnum AttType { get; set; }
}

public abstract class BaseAttribute
{
    int Id { get;set;}
    string Name { get;set;}
    AttributeTypeEnum AttType { get; set; }
}

public class RangeAttribute<T> : BaseAttribute
{
   T StartValue { get;set; }
   T EndValue { get; set; }
}

然后将每个属性与一个或多个类别相关联

public class CategoryAttribute
{
    int Id { get; set; }
    IAttribute Attribute { get; set; }
}

然后,您可以拥有针对每个类别的属性列表

public class CategoryAttributeService()
{
    public IList<CategoryAttributes> GetAttributes(int CategoryId)
    {
        return new IList<CategoryAttributes>();
    }
}

然后,您的控制器可以在ViewData.Model中返回这些属性的列表。

// controller action
public class CategoryAttributeController : Controller
{
    public ActionResult CategoryAttributes(int categoryId)
    {
        CategoryAttributeService cas = new CategoryAttributeServices();
        ViewData.Model = new CategoryAttributeViewData(categoryId)
        {
            Attributes = cas.GetAttributes(categoryId);
        };
        return View();
    }
}

让您的视图处理每个项目的类型并相应地更改每个项目的表单控件/显示,即(具有开始和结束值的范围)布尔值将具有复选框,材料可能是列表框等。 你有很多关于如何处理渲染的选择,你可以为每个属性类型创建一个单独的.ascx控件来生成表单控件,或者如下创建一个html辅助方法

<%@ Page Title="" Language="C#" Inherits="ViewPage<CategoryAttributeViewData>" %>

<% foreach(CategoryAttribute attribute in ViewData.Model.Attributes) { %>
<%= Html.RenderAttribute(attribute) %>
<% } %>

之类的辅助方法
public static string RenderAttribute(this HtmlHelper, ICategoryAttribute att)
{
    StringWriter stringWriter = new StringWriter();
    using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter))
    {
        switch(att.AttributeType)
        {
            case AttributeDataType.Boolean:
                CreateCheckBox(writer, att);
                break;
            case AttributeDataType.List:
                CreateListBox(writer, att);
                break;
            // Other types                
        }
    }
    stringWriter.ToString();
}
编辑:我有点离开了市场,所以如果我理解正确的话,每个市场都有许多类别(一对多)说美国和服装。 服装类别可以出现在许多市场中。 每个类别都有许多属性(一对多)(服装:颜色,大小),每个属性可以有多个市场(一对多)

  • 市场列表
  • 类别列表
  • MarketCategories列表
  • CategoryAttributes列表
  • 属性列表
  • AttributeMarkets列表

市场&gt; MarketCategories&gt; CategoryAttributes&gt;属性&gt; AttributeMarkets

这是对的吗?

的Mac。

答案 1 :(得分:0)

对于每个类别的模型实体,创建一个模型视图,根据当前市场过滤属性,
可能会在飞行中创建未经过滤的属性字典
或以其他方式发信号通知哪些属性要忽略/不要忽略 - 如果每个属性的过滤太多,您可以为每个市场使用单独的模型视图(使用字典)。

您也可以使用单独的视图,但这会留下大量视图 - 一个动态视图根据视图加载正确的视图模型(通过控制器查找模型视图)并获取视图模型过滤器会更加优雅。

答案 2 :(得分:0)

在数据库中设置一个如下所示的表:

Category nvarchar(*)
Market nvarchar(*)
AttributeName nvarchar(*)
AttributeType nvarchar(*)

然后在该表中存储您需要的每个属性组合(显然,可以进行一些重构,例如具有“属性”表,该表存储快速插入是否需要属性并允许用于共享属性的类别/市场组合)。

然后在您的视图中,阅读用户的类别和市场组合并动态构建表单:

在你的Page.Load表单中,实例化你需要的表单部分,给它们有意义的ID,然后在你的回发处理程序中,读取Request.Form对象中的所有数据。

一个简短的例子:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim stuff As New System.Web.UI.WebControls.TextBox()
    stuff.ID = "WOW64"
    Page.Form.Controls.Add(stuff)
End Sub

Protected Sub Submit_Click(ByVal sender As Object, ByVal e As EventArgs)
    Dim str As String = Request.Form("WOW64")
    str = str ' do something with the string'
End Sub

答案 3 :(得分:0)

使用EAV

的标准实现结束