C# XML驱动的MVC.NET分层菜单

C# XML驱动的MVC.NET分层菜单,c#,asp.net-mvc,xml,C#,Asp.net Mvc,Xml,我试图在MVC.NET中创建一个基于xml的分层菜单 <?xml version="1.0" encoding="utf-8" ?> <NavigationMenu id="1" Name="myMenu" Lang="EN"> <NavigationMenuGroup Header="Home" Name="header1" Link="/home" /> <NavigationMenuGroup Header="Manage" Name="h

我试图在MVC.NET中创建一个基于xml的分层菜单

<?xml version="1.0" encoding="utf-8" ?>
<NavigationMenu id="1" Name="myMenu" Lang="EN">
  <NavigationMenuGroup Header="Home" Name="header1" Link="/home" />
  <NavigationMenuGroup Header="Manage" Name="header2" Link="/options" />
  <NavigationMenuGroup Header="About" Name="header3"  Link="/About" >
    <NavigationMenuItem Header="Test1" Name="header5"  Link="/page1" />
    <NavigationMenuItem Header="Test2" Name="header6"  Link="/page2" />
  </NavigationMenuGroup>
</NavigationMenu>

我平移母版页以呈现部分菜单(NavMenu.ascx),数据将由自定义BaseController提供给母版页

NavMenu.ascx将生成与以下类似的代码(易于插入jQuery或simlar)

我还设置了一组要反序列化的类

    namespace MyMVC.Helpers
    {
        public class XmlSerializerHelper<T>
        {
            public Type _type;

            public XmlSerializerHelper()
            {
                _type = typeof(T);
            }

            public void Save(string path, object obj)
            {
                using (TextWriter textWriter = new StreamWriter(path))
                {
                    XmlSerializer serializer = new XmlSerializer(_type);
                    serializer.Serialize(textWriter, obj);
                }
            }

            public T Read(string path)
            {
                T result;
                using (TextReader textReader = new StreamReader(path))
                {
                    XmlSerializer deserializer = new XmlSerializer(_type);
                    result = (T)deserializer.Deserialize(textReader);
                }
                return result;
            }
        }
}
名称空间MyMVC.Helpers
{
公共类XMLRHELPER
{
公共类型_类型;
公共XMLRHELPER()
{
_类型=类型(T);
}
公共void保存(字符串路径,对象对象对象)
{
使用(TextWriter TextWriter=新StreamWriter(路径))
{
XmlSerializer serializer=新的XmlSerializer(_类型);
serializer.Serialize(textWriter,obj);
}
}
公共T读取(字符串路径)
{
T结果;
使用(文本阅读器文本阅读器=新的流阅读器(路径))
{
XmlSerializer反序列化程序=新的XmlSerializer(_类型);
结果=(T)反序列化程序。反序列化(textReader);
}
返回结果;
}
}
}

我不确定在不违反MVC原则的情况下,什么是最好的方法?

看看同样适用于XML的方法看看同样适用于XML的方法我自己也在尝试解决这个问题,并提出了以下建议。我将我的用于需要某些活动类的主导航(基于Drupal的菜单呈现):

XML:

<?xml version="1.0" encoding="utf-8" ?>
<items>
  <item title="Some Title" name="Test" text="Testing 1" link="1">
    <items>
      <item name="Test" text="Testing 1-1" link="2">
        <items>
          <item name="Test" text="About" link="/home/about" />
          <item name="Test" text="Testing 1-1-2" link="4" />
          <item name="Test" text="Testing 1-1-3" link="5" />
        </items>
      </item>
      <item name="Test" text="Testing 1-2" link="6" />
      <item name="Test" text="Testing 1-3" link="7" />
    </items>
  </item>
  <item name="Testame" text="Testing 2" link="8" />
  <item name="Test" text="Testing 3" link="9" />
  <item name="Test" text="Testing 4" link="10" />
  <item name="Test" text="Testing 5" link="11" />
  <item title="Some Title" name="Test" text="Testing 6" link="1">
    <items>
      <item name="Test" text="Testing 6-1" link="12">
        <items>
          <item name="Test" text="Testing 6-1-1" link="13" />
          <item name="Test" text="Testing 6-1-2" link="14" />
          <item name="Test" text="Testing 6-1-3" link="15" />
        </items>
      </item>
      <item name="Test" text="Testing 6-2" link="16" />
      <item name="Test" text="Testing 6-3" link="17" />
    </items>
  </item>
  <item name="Test" text="Testing 7" link="18" />
  <item name="Test" text="Testing 8" link="19">
    <items>
      <item name="Test" text="Testing 8-1" link="20" />
      <item name="Test" text="Testing 8-2" link="21" />
      <item name="Test" text="Testing 8-3" link="22" />
    </items>
  </item>
</items>
    public static class Helpers
    {

        public static MvcHtmlString Menu(this HtmlHelper helper, string name, string e = null, object attributes = null)
        {
            string filepath = helper.ViewContext.HttpContext.Server.MapPath(name + ".xml");

            XPathDocument oDoc = new XPathDocument(filepath);

            return new MvcHtmlString(GetMenuHtml(oDoc.CreateNavigator(), e, attributes));
        }

        private static string GetMenuHtml(XPathNavigator nav, string e = "ul", object attributes = null)
        {

            List<String> item = new List<String>();

            XPathNodeIterator nodes = nav.Select("items/item");

            TagBuilder holder = new TagBuilder(e);

            if (attributes != null)
            {
                IDictionary<string, object> htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(attributes);
                holder.MergeAttributes(htmlAttributes);
            }

            while (nodes.MoveNext())
            {

                TagBuilder a = new TagBuilder("a");
                TagBuilder span = new TagBuilder("span");
                TagBuilder li = new TagBuilder("li");

                string url = nodes.Current.GetAttribute("link", string.Empty);
                string text = nodes.Current.GetAttribute("text", string.Empty);
                string title = nodes.Current.GetAttribute("title", string.Empty);

                span.InnerHtml = text;

                a.MergeAttribute("href", url);

                if (!String.IsNullOrEmpty(title)) a.MergeAttribute("title", title);

                a.InnerHtml = span.ToString();

                List<String> classes = new List<String>();

                if (url == HttpContext.Current.Request.Url.AbsolutePath)
                {
                    classes.Add("active");   
                }

                if (nodes.Count == nodes.CurrentPosition)
                {
                    classes.Add("last");
                }
                else if (nodes.CurrentPosition == 1)
                {
                    classes.Add("first");
                }

                if (nodes.Current.HasChildren)
                {
                    li.InnerHtml = a.ToString() + GetMenuHtml(nodes.Current, e);

                    if (li.InnerHtml.Contains("class=\"active"))
                    {
                        classes.Add("active-trail");
                    }

                    classes.Add("leaf");
                }
                else
                {
                    li.InnerHtml = a.ToString();
                }

                if(classes.Count > 0){
                    li.MergeAttribute("class", string.Join(" ", classes.ToArray()));
                }

                item.Add(li.ToString() + "\n");

            }

            holder.InnerHtml = string.Join("", item.ToArray());

            return holder.ToString();

        }


    }
@Html.Menu("navigation", "ul")
输出

<ul>
    <li class="first active-trail leaf">
        <a href="1" title="Some Title"><span>Testing 1</span></a>
        <ul>
            <li class="first active-trail leaf"><a href="2"><span>Testing 1-1</span></a>
                <ul>
                    <li class="active first"><a href="/home/about"><span>Testing 1-1-1</span></a></li>
                    <li><a href="4"><span>Testing 1-1-2</span></a></li>
                    <li class="last"><a href="5"><span>Testing 1-1-3</span></a></li>
                </ul>
            </li>
            <li><a href="6"><span>Testing 1-2</span></a></li>
            <li class="last"><a href="7"><span>Testing 1-3</span></a></li>
        </ul>
    </li>
    <li><a href="8"><span>Testing 2</span></a></li>
    <li><a href="9"><span>Testing 3</span></a></li>
    <li><a href="10"><span>Testing 4</span></a></li>
    <li><a href="11"><span>Testing 5</span></a></li>
    <li class="leaf">
        <a href="1" title="Some Title"><span>Testing 6</span></a>
        <ul>
            <li class="first leaf"><a href="12"><span>Testing 6-1</span></a>
                <ul>
                    <li class="first"><a href="13"><span>Testing 6-1-1</span></a></li>
                    <li><a href="14"><span>Testing 6-1-2</span></a></li>
                    <li class="last"><a href="15"><span>Testing 6-1-3</span></a></li>
                </ul>
            </li>
            <li><a href="16"><span>Testing 6-2</span></a></li>
            <li class="last"><a href="17"><span>Testing 6-3</span></a></li>
        </ul>
    </li>
    <li><a href="18"><span>Testing 7</span></a></li>
    <li class="last leaf"><a href="19"><span>Testing 8</span></a>
        <ul>
            <li class="first"><a href="20"><span>Testing 8-1</span></a></li>
            <li><a href="21"><span>Testing 8-2</span></a></li>
            <li class="last"><a href="22"><span>Testing 8-3</span></a></li>
        </ul>
    </li>
</ul>

我自己试图解决这个问题,并提出了以下建议。我将我的用于需要某些活动类的主导航(基于Drupal的菜单呈现):

XML:

<?xml version="1.0" encoding="utf-8" ?>
<items>
  <item title="Some Title" name="Test" text="Testing 1" link="1">
    <items>
      <item name="Test" text="Testing 1-1" link="2">
        <items>
          <item name="Test" text="About" link="/home/about" />
          <item name="Test" text="Testing 1-1-2" link="4" />
          <item name="Test" text="Testing 1-1-3" link="5" />
        </items>
      </item>
      <item name="Test" text="Testing 1-2" link="6" />
      <item name="Test" text="Testing 1-3" link="7" />
    </items>
  </item>
  <item name="Testame" text="Testing 2" link="8" />
  <item name="Test" text="Testing 3" link="9" />
  <item name="Test" text="Testing 4" link="10" />
  <item name="Test" text="Testing 5" link="11" />
  <item title="Some Title" name="Test" text="Testing 6" link="1">
    <items>
      <item name="Test" text="Testing 6-1" link="12">
        <items>
          <item name="Test" text="Testing 6-1-1" link="13" />
          <item name="Test" text="Testing 6-1-2" link="14" />
          <item name="Test" text="Testing 6-1-3" link="15" />
        </items>
      </item>
      <item name="Test" text="Testing 6-2" link="16" />
      <item name="Test" text="Testing 6-3" link="17" />
    </items>
  </item>
  <item name="Test" text="Testing 7" link="18" />
  <item name="Test" text="Testing 8" link="19">
    <items>
      <item name="Test" text="Testing 8-1" link="20" />
      <item name="Test" text="Testing 8-2" link="21" />
      <item name="Test" text="Testing 8-3" link="22" />
    </items>
  </item>
</items>
    public static class Helpers
    {

        public static MvcHtmlString Menu(this HtmlHelper helper, string name, string e = null, object attributes = null)
        {
            string filepath = helper.ViewContext.HttpContext.Server.MapPath(name + ".xml");

            XPathDocument oDoc = new XPathDocument(filepath);

            return new MvcHtmlString(GetMenuHtml(oDoc.CreateNavigator(), e, attributes));
        }

        private static string GetMenuHtml(XPathNavigator nav, string e = "ul", object attributes = null)
        {

            List<String> item = new List<String>();

            XPathNodeIterator nodes = nav.Select("items/item");

            TagBuilder holder = new TagBuilder(e);

            if (attributes != null)
            {
                IDictionary<string, object> htmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(attributes);
                holder.MergeAttributes(htmlAttributes);
            }

            while (nodes.MoveNext())
            {

                TagBuilder a = new TagBuilder("a");
                TagBuilder span = new TagBuilder("span");
                TagBuilder li = new TagBuilder("li");

                string url = nodes.Current.GetAttribute("link", string.Empty);
                string text = nodes.Current.GetAttribute("text", string.Empty);
                string title = nodes.Current.GetAttribute("title", string.Empty);

                span.InnerHtml = text;

                a.MergeAttribute("href", url);

                if (!String.IsNullOrEmpty(title)) a.MergeAttribute("title", title);

                a.InnerHtml = span.ToString();

                List<String> classes = new List<String>();

                if (url == HttpContext.Current.Request.Url.AbsolutePath)
                {
                    classes.Add("active");   
                }

                if (nodes.Count == nodes.CurrentPosition)
                {
                    classes.Add("last");
                }
                else if (nodes.CurrentPosition == 1)
                {
                    classes.Add("first");
                }

                if (nodes.Current.HasChildren)
                {
                    li.InnerHtml = a.ToString() + GetMenuHtml(nodes.Current, e);

                    if (li.InnerHtml.Contains("class=\"active"))
                    {
                        classes.Add("active-trail");
                    }

                    classes.Add("leaf");
                }
                else
                {
                    li.InnerHtml = a.ToString();
                }

                if(classes.Count > 0){
                    li.MergeAttribute("class", string.Join(" ", classes.ToArray()));
                }

                item.Add(li.ToString() + "\n");

            }

            holder.InnerHtml = string.Join("", item.ToArray());

            return holder.ToString();

        }


    }
@Html.Menu("navigation", "ul")
输出

<ul>
    <li class="first active-trail leaf">
        <a href="1" title="Some Title"><span>Testing 1</span></a>
        <ul>
            <li class="first active-trail leaf"><a href="2"><span>Testing 1-1</span></a>
                <ul>
                    <li class="active first"><a href="/home/about"><span>Testing 1-1-1</span></a></li>
                    <li><a href="4"><span>Testing 1-1-2</span></a></li>
                    <li class="last"><a href="5"><span>Testing 1-1-3</span></a></li>
                </ul>
            </li>
            <li><a href="6"><span>Testing 1-2</span></a></li>
            <li class="last"><a href="7"><span>Testing 1-3</span></a></li>
        </ul>
    </li>
    <li><a href="8"><span>Testing 2</span></a></li>
    <li><a href="9"><span>Testing 3</span></a></li>
    <li><a href="10"><span>Testing 4</span></a></li>
    <li><a href="11"><span>Testing 5</span></a></li>
    <li class="leaf">
        <a href="1" title="Some Title"><span>Testing 6</span></a>
        <ul>
            <li class="first leaf"><a href="12"><span>Testing 6-1</span></a>
                <ul>
                    <li class="first"><a href="13"><span>Testing 6-1-1</span></a></li>
                    <li><a href="14"><span>Testing 6-1-2</span></a></li>
                    <li class="last"><a href="15"><span>Testing 6-1-3</span></a></li>
                </ul>
            </li>
            <li><a href="16"><span>Testing 6-2</span></a></li>
            <li class="last"><a href="17"><span>Testing 6-3</span></a></li>
        </ul>
    </li>
    <li><a href="18"><span>Testing 7</span></a></li>
    <li class="last leaf"><a href="19"><span>Testing 8</span></a>
        <ul>
            <li class="first"><a href="20"><span>Testing 8-1</span></a></li>
            <li><a href="21"><span>Testing 8-2</span></a></li>
            <li class="last"><a href="22"><span>Testing 8-3</span></a></li>
        </ul>
    </li>
</ul>

菜单中的每一项都是标题吗?菜单中的每一项都是标题吗?这很有用,但我正在寻找一种简洁的方式来手动滚动此:)这很有用,但我正在寻找一种简洁的方式来手动滚动此:)