Передача ссылочных / статических данных через viewmodel в представление в MVC3

#c# #asp.net-mvc

#c# #asp.net-mvc

Вопрос:

Я создал класс для хранения некоторых статических данных:

 static public class ReferenceData
    {
        [DisplayName("Status")]
        public IEnumerable<SelectListItem> StatusType
        {
            get
            {
                return new[]
                    {
                        new SelectListItem { Value = "0", Text = "Release" },
                        new SelectListItem { Value = "1", Text = "Beta" },
                        new SelectListItem { Value = "2", Text = "Alpha" },
                    };
            }
        }
    }
  

Теперь я хотел бы использовать данные этого класса для заполнения выпадающего списка в представлении. У меня есть следующая модель представления:

 public class adminViewModel
{
    public HouseData   HouseData { get; set; }
    public string Status { get; set; }
    public ReferenceData ReferenceData { get; } // <<<<<< My problem here
}


@Html.DropDownListFor(
  x => x.Status,
  new SelectList(Model.ReferenceData.StatusType, "Value", "Text"),
  new { style = "display: inline;" }
)
  

Проблема для меня в том, что я не уверен, является ли это допустимым способом сделать это, потому что я использую статический класс, и когда у меня есть get; там внутри {}, он жалуется во время компиляции сообщением об ошибке, в котором говорится:

 static types cannot be used as return types
  

Действительно ли мне нужно сделать его нестатическим и создать экземпляр класса, прежде чем я смогу использовать его в viewmodel, даже если данные всегда статичны?

Ответ №1:

Это недопустимый C #. Вместо этого вы могли бы использовать статический метод:

 public static class ReferenceData
{
    public static IEnumerable<SelectListItem> GetStatusType()
    {
        return new[]
        {
            new SelectListItem { Value = "0", Text = "Release" },
            new SelectListItem { Value = "1", Text = "Beta" },
            new SelectListItem { Value = "2", Text = "Alpha" },
        };
    }
}
  

и затем :

 public class AdminViewModel
{
    public string Status { get; set; }

    [DisplayName("Status")]
    public IEnumerable<SelectListItem> Statuses
    {
        get
        {
            return ReferenceData.GetStatusType();
        }
    }
}
  

наконец, в представлении:

 @Html.DropDownListFor(
    x => x.Status,
    new SelectList(Model.Statuses, "Value", "Text"),
    new { style = "display: inline;" }
)
  

Комментарии:

1. за исключением того, что данные такого типа должны находиться в viewbag, или viewdata, или tempdata. куда угодно, кроме viewmodel. эти данные не имеют никакого отношения к модели.

2. @nathan gonzalez, ViewBag и ViewData являются самыми злыми вещами в ASP.NET В MVC для меня такого рода данных определенно не должно быть. Временные данные, я не знаю => есть несколько редких случаев, когда это может быть полезно. Я думаю, вы имеете в виду, что эти данные могут быть жестко запрограммированы в методе репозитория, который запрашивает действие контроллера для заполнения модели. Тогда я бы согласился с вами.

3. жесткий код в репозитории? я не думаю, что я когда-либо сделал бы это. почему вы ненавидите viewbag и viewdata. этот тип данных — это то, для чего они предназначены. viewmodel предназначена для модели views, частью которой эти данные явно не являются.

4. @nathan gonzalez, да, у меня была бы реализация моего интерфейса репозитория, которую я бы, например, вызвал AdminOptionsMemory , потому что, например, у меня нет базы данных, и я не хочу хранить эти значения в файлах, я просто хочу, чтобы они были в памяти. Что касается ViewBag / ViewData, то они вносят слабую типизацию в представления, если вы используете их, это означает, что вы не используете строго типизированные представления и модели представлений, если вы используете их, вы не получаете Intellisense, если вы используете их, вам нужно выполнять приведения в ваших представлениях, чтобы вызвать надлежащую перегрузку метода, … и я могу продолжить с этим

5. я не говорю, что вы не должны использовать строго типизированное представление, я полностью за использование viewmodel для данных представления, связанных с моделью. и я получаю слабо типизированную проблему, но для данных, которых нет в модели views, viewdata — это место, куда их можно поместить. я полагаю, согласен с несогласием.

Ответ №2:

Вы уверены, что хотите, чтобы ваш класс был статическим, а не свойство? Если у вас есть статическое свойство, вам не нужно создавать экземпляр, чтобы получить доступ к свойству. Дополнительная информация: Статические классы и члены статического класса (руководство по программированию на C #):

Комментарии:

1. Я хотел сделать класс статическим, чтобы мне не пришлось создавать его экземпляр. Это правильное утверждение? Я удалил статику из класса и добавил статику к типу состояния. Затем в модели представления я получаю другое сообщение: …..ReferenceData.get’ должен объявить тело, потому что оно не помечено как abstract или extern. Автоматически реализуемые свойства должны определять как методы доступа get, так и set.

2. сделайте свойство статическим вместо класса

3. @DavidH если вы хотите, чтобы ReferenceData были автоматически реализованным свойством, доступным только для чтения, тогда вам следует написать public ReferenceData ReferenceData { get; private set; }

Ответ №3:

Вы хотите сделать это:

     public class ReferenceData
    {
        private static readonly SelectListItem[] Items = new[]
                {
                    new SelectListItem { Value = "0", Text = "Release" },
                    new SelectListItem { Value = "1", Text = "Beta" },
                    new SelectListItem { Value = "2", Text = "Alpha" },
                };

        [DisplayName("Status")]
        public IEnumerable<SelectListItem> StatusType
        {
            get { return Items; }
        }
    }
  

(сделайте элементы статическими при использовании экземпляра класса).

Вы также можете использовать синглтон:

     public class ReferenceData
    {
        private static readonly ReferenceData _instance = new ReferenceData();

        private ReferenceData()
        {

        }

        public ReferenceData Instance { get { return _instance; } }

        [DisplayName("Status")]
        public IEnumerable<SelectListItem> StatusType
        {
            get
            {
                return new[]
                {
                    new SelectListItem { Value = "0", Text = "Release" },
                    new SelectListItem { Value = "1", Text = "Beta" },
                    new SelectListItem { Value = "2", Text = "Alpha" },
                };
            }
        }
    }
  

И использовать это в вашей модели:

 public class adminViewModel
{
    public HouseData   HouseData { get; set; }
    public string Status { get; set; }
    public ReferenceData ReferenceData { get {return ReferenceData.Instance; } }
}
  

Комментарии:

1. Ваш ответ работает очень хорошо. Только один вопрос. Как я могу получить доступ к StatusType в программе C #. Я попытался выполнить var data1 = new ReferenceData(); но он выдает сообщение об ошибке: Ссылочные данные недоступны из-за их уровня защиты.

2. var data = ReferenceData.Instance.StatusType

Ответ №4:

Прежде всего создайте свою модель следующим образом..

 public class ReferenceData
{
    public string SelectRuleId { get; set; }

    public IEnumerable<SelectListItem> StatusType
    {
        get
        {
            return new[]
            {
                new SelectListItem { Value = "0", Text = "Release" },
                new SelectListItem { Value = "1", Text = "Beta" },
                new SelectListItem { Value = "2", Text = "Alpha" },
            };
        }
    }
}
  

Затем создайте новое действие в любом контроллере, подобном этому..

    public ActionResult About()
    {
        var model = new ReferenceData();

        ViewBag.Message = "DropDown Selected For ";

        return View(model);
    }
  

Затем используйте этот HTML-код в своем представлении действий…

 @model MVCDropDownList.Models.AnswersViewModel

 @using (Html.BeginForm())  
    {  @Html.DropDownListFor(x => x.SelectRuleId , new SelectList(Model.StatusType, "Value", "Text"), new { id = "DId" })  
    }