如何显示客户特定信息,避免使用xslt?

时间:2011-10-31 14:58:19

标签: asp.net-mvc-3 xslt

我的工作地点目前为几个客户维护一个网站,该网站使用经典的asp编写。每个客户都需要专门为他们编写网站的特定部分。

例如,客户A要求以下列格式输入,显示和存储地址:

Address Line 1
Address Line 2
Address Line 3
Address Line 4
Address Line 5
Postcode

而客户B要求输入,显示和存储地址为:

Street
Town
City
Postcode

依此类推......

因此,我的工作地点采用了将数据作为xml存储在数据库中并使用xsl(我目前知之甚少)将数据转换为html的路径。

因此,如果我们需要用户通过html表单提供信息,则使用xsl转换xml。然后,用户输入信息并通过表单提交数据。然后使用asp页面验证数据。此asp页面特定于用于显示表单的xsl页面。因此,我们现在处于一个位置,对于每个客户,我们有许多xsl页面和许多客户特定的asp页面(大部分代码都是重复的)。

我被要求将网站移至asp.net mvc3并删除大部分重复内容,并想知道什么是满足此客户特定字段功能的最佳方式。我倾向于将数据保存为xml,因为使用com组件访问数据库层,我想在不改变的情况下重用它们。

我已经读过我可以保留xsl页面并开发一个xslt视图引擎来显示html。但是,我不确定在用户提交表单时如何验证数据?

如果我要完全删除xsl,那么显示客户特定字段的最佳方法是什么?或者我是否必须拥有客户特定的观点并查看模型?

任何想法都会非常感激。

1 个答案:

答案 0 :(得分:1)

如果您真的想要使用MVC的内置验证/模型功能,我认为您最好的选择是使用XmlSerializer或使用DataContracts来开发与XML串行化的内容(一次)它从COM对象中检索,因此您不需要重新编码那些),然后您可以将这些类用作MVC的模型,并使用标准数据注释来利用更丰富的MVC模型功能并跳过XSL步骤完全。

要将其与自定义特定视图结合使用,我通常会覆盖默认视图引擎,使其实际上会尝试更具体的客户/对象名称,然后回退到一般名称。

此视图引擎允许您传递视图以传递视图名称(即。FallbackViewEngine.BuildViewName("General", "Customer Name"),它将首先查找“General.Customer Name.cshtml”,然后查找“General.cshtml”作为后备这样,您就可以在视图文件夹中实际使用客户特定的视图。

public class FallbackViewEngine : RazorViewEngine
{
    const string NameSeparator = "==";
    const string FileSeparator = ".";

    public static string BuildViewName(string root, params string[] fallbackList)
    {
        if (string.IsNullOrWhiteSpace(root)) throw new ArgumentNullException("root");
        if (fallbackList == null) throw new ArgumentNullException("fallbackList");

        var sb = new StringBuilder(root);

        foreach (var s in fallbackList)
        {
            if (string.IsNullOrWhiteSpace(s)) continue;

            sb.Append(NameSeparator);
            sb.Append(s);
        }

        return sb.ToString();
    }

    public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
        if (string.IsNullOrWhiteSpace(viewName)) throw new ArgumentNullException("viewName");

        var names = viewName.Split(new string[] {NameSeparator}, StringSplitOptions.None);

        var searched = new List<string>();

        //iterate from specific to general
        for (var i = names.Length; i >= 1; i--)
        {
            var result = base.FindView(controllerContext, string.Join(FileSeparator, names, 0, i), masterName, useCache);

            if (result.View != null)
            {
                return result;
            }
            else
            {
                searched.AddRange(result.SearchedLocations);
            }
        }

        return new ViewEngineResult(searched);                        
    }
}