Drop down list at layout page - MVC

2019-05-27 04:24发布

问题:

My problem: drop down list at layout page.

I've read this post: ASP.NET MVC Razor pass model to layout it's more or less similar to my problem. In one of comments Mattias Jakobsson wrote that: "But a common solution is to use RenderAction to render parts that need their own data in the layout page". So ok I've created layout page with @Html.Action() that render my drop dwon list with a date from the db. Everything's perfect. But...

  1. I have two pages, for example: 'Home', 'About' and my drop down list (ddl) at layout page
  2. How to achive that when I'm at 'Home' and I changed selection in ddl it refresh 'Home' page and when I'm at 'About' it refresh 'About' page.
  3. How to store selected ddl value through pages?

Part of Layout.cshtml code:

    .
    .
    <body>
    <header id="top" class="grid-full-margin">

        <strong id="logo" class="grid-304"><a href="/"><img src="/images/logo.png" ></a></strong>
        @Html.ActionLink(@Resources.Resource.BackToIntranet, "Index", "Home", null, new {@class = "link link-home grid-position-left"})

        <h1>@Resources.Resource.SiteTitle</h1>

        <a href="#" class="link link-help">@Resources.Resource.LayoutHelp</a>

        <nav clss="grid-896">

            <ul>
                <li>@Html.ActionLink(Resources.Resource.LayoutMenuItem1, "Index", "Home")</li>
                <li>@Html.ActionLink(Resources.Resource.LayoutMenuItem2, "Index", "ClimaticStation")</li>
                <li>@Html.ActionLink(Resources.Resource.LayoutMenuItem3, "Index", "ClimaticPoint")</li>
                <li>@Html.ActionLink(Resources.Resource.LayoutMenuItem4, "Index", "IcewaterExchanger")</li>
                <li>@Html.ActionLink(Resources.Resource.LayoutMenuItem5, "Index", "Pipeline")
                    <ul>
                        <li>@Html.ActionLink("Zestawienie", "YearsLength", "Pipeline")</li>
                    </ul>
                </li>
            </ul>

            <div class="mod-select-list tbl-actions">
                @Html.Partial("~/Views/Shared/Partials/LoginPartial.cshtml")
            </div>
        </nav>



    </header>
    <form action="#">
        @Html.Action("VariantsDdl", "MyBase")
    </form> 

    @RenderBody()
    .
    .

Part of MyBaseController.cs

   public class MyBaseController : Controller
{
   [ChildActionOnly]
    public ActionResult VariantsDdl()
    {
        var dataFromDb = GetDataFromDB(); // it's not importstn right now
        return this.PartialView("~/Views/Shared/Partials/VariantsDdlPartial.cshtml", dataFromDb);
    }
   .
   .
   }

Regards, Marcin

回答1:

ok I've managed to solve this problem and I want to know your opinion abut my solution.

_Layout.cshtml looks the same way like at first post, so belowe is only most important part for this question (drop down list at layout)

    <div style="float: right;">
            @Html.Action("VariantsDdl", "MyBase")
    </div>

Action: VariantsDdl is implemented at MyBaseController. This action loads selected variant id from session or if it's null then from web.config (in this situation it's project requirement that at least one variant must be present at db and its id must be specified in config):

    [ChildActionOnly]
    public ActionResult VariantsDdl()
    {
        long defaultVariantID;
        long.TryParse(System.Configuration.ConfigurationManager.AppSettings["DefaultVariantId"], out defaultVariantID);

        if (System.Web.HttpContext.Current.Session["mySelectedVariant"] != null)
        {
            long.TryParse(System.Web.HttpContext.Current.Session["mySelectedVariant"].ToString(), out defaultVariantID);
        }

        var variants = this.db.warianties.ToList();
        var items = new List<SelectListItem>();
        foreach (var variant in variants)
        {
            var selectedItem = false;
            if(variant.id == defaultVariantID)
            {
                selectedItem = true;
            }

            items.Add(new SelectListItem { Selected = selectedItem, Text = variant.nazwa, Value = variant.id.ToString() });
        }

        return this.PartialView("~/Views/Shared/Partials/VariantsDdlPartial.cshtml", items);
    }

Partial view and post action that stores selected variant id to session:

    @model IEnumerable<SelectListItem>

    <label for="field">Current variant</label>
    @Html.DropDownList("Varaints", Model, new { id = "variantsDdl" })

   <script type="text/javascript">
$(function () {
    $('#variantsDdl').change(function () {
        var val = $('#variantsDdl').val()
        $.ajax({
            type: "POST",
            url: '@Url.Action("ChangeVariant", "MyBase")' + '/' + val,
            success: function (result) {
                location.reload();
            },
            error: function (data) { alert('Error'); }
        });

    });
});

Partial View post action 'ChangeVariant', saves selected variant id to session:

   [HttpPost]
    public ActionResult ChangeVariant(long id = 0)
    {
        System.Web.HttpContext.Current.Session["mySelectedVariant"] = id;

        return null;
    }

This is solution for my requirements: 1. DDL at layout 2. Refresh current page at DDL 'onchange' 3. Keep selected DDL value through pages

Please comment if it's appropriate solution or maybe should I go different way?

Regards, Marcin