Получение текущего сохраненного значения из базы данных в форме каскадных выпадающих меню в режиме редактирования C # MVC - PullRequest
0 голосов
/ 10 декабря 2018

Я ищу способ отображения выбранной и сохраненной величины «Уже» в форме редактирования.Если пользователь выбирает изменить, он будет заполнять раскрывающийся список.Здесь есть похожий вопрос, подобный этому, но это не MVC, и, к сожалению, на него не было ответа, и тот, кто его опубликовал, пошел в другом направлении.Я уверен, что это может быть достигнуто с помощью javascript / ajax.Я не программист javascript / ajax, поэтому я застрял в том, что изменить.Каскадный выпадающий список заполняется правильно и работает нормально.Кроме того факта, что вам действительно нужно сначала выбрать другую страну, а затем вернуться к исходной компании для заполнения списка штатов.Текущий код JavaScript / ajax заполняет раскрывающийся список, а затем сохраняет идентификаторы «Страна, Штат, Город» в сохраняемой записи.Это также сбивает с толку, потому что я не хочу видеть Id в сохраненном значении, но фактическое имя.Мой код ниже.

РЕДАКТИРОВАТЬ Это было отмечено как дубликат, однако на самом деле это не так.Ключевым фактором в этом Вопросе являются «Каскадные выпадающие списки», в которых 1 раскрывающийся список зависит от того, перед которым он получает необходимую информацию.В начале у меня не было проблемы с этим.Теперь я делаю!Я реализовал то, что было сделано в этом посте Html.DropdownListДля выбранного значения не устанавливается .Теперь я могу видеть выбранные элементы, которые выбраны в выпадающих списках.Это здорово, но это сломало мой каскадный эффект.Теперь он просто заполняет весь список в каждом раскрывающемся списке.Когда я пытаюсь сохранить его, он не будет, теперь я получаю сообщение об ошибке сохранения -

System.InvalidOperationException: 'The ViewData item that has the key 'Country' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.'

Так что предлагаемые решения действительно касаются только части проблемы, с которой я столкнулся.Новый код приведен ниже, и мне также пришлось использовать 'public IEnumerable States {get;задавать;} 'в моей модели представления предлагаемые' public SelectList States {get;set;} 'не работал, так как искал IEnumerable.

РЕДАКТИРОВАТЬ - Изменены 3 выпадающих.Вот 3 выпадающих списка на странице бритвы:

                            <div class="form-group row">
                            @Html.LabelFor(model => model.Country, htmlAttributes: new { @class = "control-label col-md-3" })
                            <div class="col-md-8">
                                @Html.DropDownListFor(model => Model.Country, Model.Countries, "Select Country", new { @class = "form-control", @id = "ddlCountry" })
                                @Html.ValidationMessageFor(model => model.Country, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group row">
                            @Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-3" })
                            <div class="col-md-8">
                                @Html.DropDownListFor(model => model.State, Model.States, "Select State", new { @class = "form-control", @id = "ddlState" })
                                @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
                            </div>
                        </div>

                        <div class="form-group row">
                            @Html.LabelFor(model => model.City, htmlAttributes: new { @class = "control-label col-md-3" })
                            <div class="col-md-8">

                                @Html.DropDownListFor(model => model.City, Model.Cities, "Select City" , new { @class = "form-control", @id = "ddlCity" })
                                @Html.ValidationMessageFor(model => model.City, "", new { @class = "text-danger" })
                            </div>
                        </div>

Это JavaScript / Ajax: ПРИМЕЧАНИЕ. Я пытался изменить -

"<option value="' + value.StateId + '">"

на:

"<option value="' + value.Name + '">"

Но не работает, так как код использует "id" для получения следующего выпадающего списка.

<script type="text/javascript">

$(function () {
    $('#ddlCountry').change(function () {
        $.ajax({
            type: "post",
            url: "/Customer/GetStates",
            data: { countryId: $('#ddlCountry').val() },
            datatype: "json",
            traditional: true,
            // *can you add the following error callback in your code and update what comes in the console log?*
            error: function(_, err) {
                console.log(_, err)
            },
            success: function (data) {
                $.each(data, function (index, value) {
                    $('#ddlState').append('<option value="' + value.StateId + '">' + value.StateName + '</option>');
                });
            }
        });
    });

    $('#ddlState').change(function () {
        $.ajax({
            type: "post",
            url: "/Customer/GetCities",
            data: { stateId: $('#ddlState').val() },
            datatype: "json",
            traditional: true,
            error: function(_, err) {
                console.log(_, err)
            },
            success: function (data) {
                $.each(data, function (index, value) {
                    $('#ddlCity').append('<option value="' + value.CityId + '">' + value.CityName + '</option>');
                });
            }
        });
    });
});

EDIT - Новое действие контроллера.Вот мои действия контроллера:

        public ActionResult UserEditAddress(Guid guid)
    {

        if (guid == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Addresses addresses = db.Addresses.Find(guid);
        if (addresses == null)
        {
            return HttpNotFound();
        }
        var model = new EditAddressViewModel();
        model.AddressUI = addresses.AddressUI;
        model.Line1 = addresses.Line1;
        model.Line2 = addresses.Line2;
        model.Country = addresses.Country;
        model.State = addresses.State;
        model.City = addresses.City;
        model.ZipCode = addresses.ZipCode;
        model.CompanyId = addresses.CompanyId;
        model.Countries = new SelectList(db.Countries, "CountryId", "CountryName", addresses.Country);
        model.States = new SelectList(db.States, "StateId", "StateName", addresses.State);
        model.Cities = new SelectList(db.Cities, "CityId", "CityName", addresses.City);

        return View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult UserEditAddress(EditAddressViewModel model)
    {
        var userId = User.Identity.GetUserId();
        if (!ModelState.IsValid)
        {
            return View(model);
        }
        Addresses addresses = db.Addresses.Find(model.AddressUI);
        addresses.Line1 = model.Line1;
        addresses.Line2 = model.Line2;
        addresses.Country = model.Country;
        addresses.State = model.State;
        addresses.City = model.City;
        addresses.ZipCode = model.ZipCode;
        addresses.CompanyId = model.CompanyId;

        db.Entry(addresses).Property(x => x.AddressId).IsModified = false;
        db.Entry(addresses).Property(x => x.IsBilling).IsModified = false;
        db.Entry(addresses).Property(x => x.IsShipping).IsModified = false;
        db.Entry(addresses).Property(x => x.ContactName).IsModified = false;
        db.Entry(addresses).Property(x => x.EmailAddress).IsModified = false;
        db.Entry(addresses).Property(x => x.PhoneNumber).IsModified = false;
        db.Entry(addresses).Property(x => x.FaxNumber).IsModified = false;
        //db.Entry(addresses).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index", "Customer", new { UserId = userId });

    }

    // Get States
    public JsonResult GetStates(string countryId)
    {
        int Id;
        Id = Convert.ToInt32(countryId);

        var states = from a in db.States where a.CountryId == Id select a;
        return Json(states);

    }

    // Get Cities
    public JsonResult GetCities(string stateId)
    {
        int Id;
        Id = Convert.ToInt32(stateId);

        var cities = from a in db.Cities where a.StateId == Id select a;
        return Json(cities);
    }

Ваша помощь будет высоко оценена, так как я потратил очень много времени, пытаясь найти решение для этого.Заранее благодарю за помощь.

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Благодаря многим исследованиям, и я до сих пор не до конца уверен, что это правильный способ сделать это, но он работает.Поэтому, если вам нужен каскадный выпадающий список с редактированием, я так и сделал.

Я начну с модели представления.

    public class EditAddressViewModel
    {
    public Guid AddressUI { get; set; }

    [Display(Name = "Billing Address?")]
    [UIHint("_IsStatus")]
    public bool IsBilling { get; set; }

    [Display(Name = "Shipping Address?")]
    [UIHint("_IsStatus")]
    public bool IsShipping { get; set; }

    [Display(Name = "Location Name")]
    [Required(ErrorMessage = "Location name is required")]
    public string LocationName { get; set; }

    [Display(Name = "Contact Name")]
    [Required(ErrorMessage = "Contact name is required")]
    public string ContactName { get; set; }

    [Display(Name = "Address")]
    public string Line1 { get; set; }

    [Display(Name = "Address 2")]
    [Required(ErrorMessage = "Address line 2 is required - Should be your address or PO Box")]
    public string Line2 { get; set; }

    [Display(Name = "Country")]
    [Required(ErrorMessage = "Country name is required")]
    public int Country { get; set; }
    public IEnumerable<SelectListItem> Countries { get; set; }

    [Display(Name = "State")]
    [Required(ErrorMessage = "State name is required")]
    public int State { get; set; }
    public IEnumerable<SelectListItem> States { get; set; }

    [Display(Name = "City")]
    [Required(ErrorMessage = "City name is required")]
    public int City { get; set; }
    public IEnumerable<SelectListItem> Cities { get; set; }

    [Display(Name = "ZipCode")]
    public string ZipCode { get; set; }

    [Display(Name = "Contact Email")]
    [Required(ErrorMessage = "Email contact is required")]
    [DataType(DataType.EmailAddress)]
    [StringLength(320)]
    [RegularExpression(@"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", ErrorMessage = "Enter a valid email address")]
    public string EmailAddress { get; set; }

    [Display(Name = "Phone Number")]
    [Required(ErrorMessage = "Phone number is required")]
    [DataType(DataType.PhoneNumber)]
    [StringLength(12)]
    [RegularExpression(@"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Enter a valid phone number")]
    public string PhoneNumber { get; set; }

    [Display(Name = "Fax Number")]
    [DataType(DataType.PhoneNumber)]
    [StringLength(12)]
    [RegularExpression(@"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", ErrorMessage = "Enter a valid phone number")]
    public string FaxNumber { get; set; }

    public int CompanyId { get; set; }

    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm}", ApplyFormatInEditMode = false)]
    public DateTime CreatedDate { get; set; }

    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd HH:mm}", ApplyFormatInEditMode = false)]
    public DateTime LastUpdated { get; set; }

}

Следующая вещь - это контроллер.

    // Customer Input
    // GET: Addresses/Edit?guid=56A792FE-28D1-4D1D-8F59-21DE1EABA2FB
    // TO DO - Create Route in APP_Start RouteConfig for better looking link.
    [Authorize(Roles = "CompanyAdmin")]
    public ActionResult UserEditAddress(Guid guid)
    {
        if (guid == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        AddressEdit addresses = db.AddressEdit.Find(guid);
        if (addresses == null)
        {
            return HttpNotFound();
        }
        var model = new EditAddressViewModel();
        model.AddressUI = addresses.AddressUI;
        model.Line1 = addresses.Line1;
        model.Line2 = addresses.Line2;
        model.Country = addresses.Country;
        model.State = addresses.State;
        model.City = addresses.City;
        model.ZipCode = addresses.ZipCode;
        model.Countries = new SelectList(db.Countries, "CountryId", "CountryName", addresses.Country);
        model.States = new SelectList(db.States, "StateId", "StateName", addresses.State);
        model.Cities = new SelectList(db.Cities, "CityId", "CityName", addresses.City);

        return View(model);
    }

    // POST: Addresses/Edit?guid=56A792FE-28D1-4D1D-8F59-21DE1EABA2FB
    // TO DO - Create Route in APP_Start RouteConfig for better looking link.
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult UserEditAddress([Bind(Include = "AddressUI,Line1,Line2,Country,State,City,ZipCode,CompanyId")] AddressEdit addresses)
    {
        var userId = User.Identity.GetUserId();
        if (ModelState.IsValid)
        { 
            db.Entry(addresses).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index", "Customer", new { UserId = userId });
        }

        return View(addresses);
    }

    // Get States
    public JsonResult GetStates(string countryId)
    {
        int Id;
        Id = Convert.ToInt32(countryId);

        var states = from a in db.States where a.CountryId == Id select a;
        return Json(states);

    }


    // Get Cities
    public JsonResult GetCities(string stateId)
    {
        int Id;
        Id = Convert.ToInt32(stateId);

        var cities = from a in db.Cities where a.StateId == Id select a;
        return Json(cities);
    }

Обратите внимание, что я использую Guid.Это было сделано для того, чтобы клиент не мог увидеть «идентификатор» записи и изменить его в ссылке для просмотра других данных клиента.Я также реализовал представление SQL по 2 причинам.Идентификатор используется для других процедур и в рамках сущности должен быть ключом.Поэтому я создал представление SQL, чтобы я мог использовать прикрепленную к нему модель и поставить Guid в качестве ключа.Также используется для целей обновления только части информации в таблице при редактировании, а не всех полей, поэтому у меня есть только поля в модели, которые необходимо обновить.

Представление SQL - Модель

namespace MyProject.BusinessModels.Entities
{
    public class AddressEdit
    {
    [Key]
    public Guid AddressUI { get; set; }
    [Display(Name = "Address")]
    public string Line1 { get; set; }
    [Display(Name = "Address 2")]
    public string Line2 { get; set; }
    [Display(Name = "Country")]
    public int Country { get; set; }
    [Display(Name = "State")]
    public int State { get; set; }
    [Display(Name = "City")]
    public int City { get; set; }
    [Display(Name = "ZipCode")]
    public string ZipCode { get; set; }
    }
}

А вот Страница бритвы с выпадающими списками для страны, штата и города.Эта настройка возвращает страницу редактирования с уже выбранными значениями в базе данных.Они целые.В раскрывающихся списках отображаются значения String из 3 отдельных таблиц, содержащих имена данных и соответствующие им идентификаторы.Функции javascript / ajax не будут работать, просто удаляя списки, потому что текущее состояние уже получило полный список каждой из 3 таблиц.Поэтому мне пришлось добавить кнопку очистки, охватывающую весь сценарий, чтобы он был сфокусирован после очистки.Таким образом, это устанавливает ddl страны на 0 и очищает список для штата и города.Теперь с помощью скрипта работает каскадный эффект, и вы можете изменять значения для обновления.Если пользователь никогда не очищает их и изменяет только другое поле в форме, он сохранит значения «Выбранные».Если они очистят форму и попытаются отправить ее, они получат сообщение об ошибке, поскольку поля обязательны для заполнения.

@model MyProject.Models.EditAddressViewModel
@using Microsoft.AspNet.Identity
@{
ViewBag.Title = "UserEdit";
Layout = "~/Views/Shared/CustomerDashboardLayout.cshtml";
}

<br />

<div class="row">
    <div class="col-lg-12">
        <p>
            @{ var userId = User.Identity.GetUserId(); }

            @Html.ActionLink("Back to List", "Index", "Customer", new { UserId = userId }, new { @class = "btn btn-primary" })
        </p>
    </div>
    <!-- /.col-lg-12 -->
</div>
<div class="row">
    <div class="col-lg-6">
        <div class="tile">
            <h3 class="tile-title">Edit Address</h3>
            <div class="tile-body">
                @using (Html.BeginForm())
                {
                    @Html.AntiForgeryToken()

                <div class="form-horizontal">

                    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

                    @Html.HiddenFor(model => model.AddressUI)

                    <div class="form-group row">
                        @Html.LabelFor(model => model.Line1, htmlAttributes: new { @class = "control-label col-md-3" })
                        <div class="col-md-8">
                            @Html.EditorFor(model => model.Line1, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.Line1, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group row">
                        @Html.LabelFor(model => model.Line2, htmlAttributes: new { @class = "control-label col-md-3" })
                        <div class="col-md-8">
                            @Html.EditorFor(model => model.Line2, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.Line2, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group row">
                        @Html.LabelFor(model => model.Country, htmlAttributes: new { @class = "control-label col-md-3" })
                        <div class="col-md-8">
                            @Html.DropDownListFor(model => Model.Country, Model.Countries, "Select Country", new { @class = "form-control", @id = "ddlCountry" })
                            @Html.ValidationMessageFor(model => model.Country, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group row">
                        @Html.LabelFor(model => model.State, htmlAttributes: new { @class = "control-label col-md-3" })
                        <div class="col-md-8">
                            @Html.DropDownListFor(model => model.State, Model.States, "Select State", new { @class = "form-control", @id = "ddlState" })
                            @Html.ValidationMessageFor(model => model.State, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group row">
                        @Html.LabelFor(model => model.City, htmlAttributes: new { @class = "control-label col-md-3" })
                        <div class="col-md-8">

                            @Html.DropDownListFor(model => model.City, Model.Cities, "Select City", new { @class = "form-control", @id = "ddlCity" })
                            @Html.ValidationMessageFor(model => model.City, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="form-group row">
                        @Html.LabelFor(model => model.ZipCode, htmlAttributes: new { @class = "control-label col-md-3" })
                        <div class="col-md-8">
                            @Html.EditorFor(model => model.ZipCode, new { htmlAttributes = new { @class = "form-control" } })
                            @Html.ValidationMessageFor(model => model.ZipCode, "", new { @class = "text-danger" })
                        </div>
                    </div>

                    <div class="tile-footer">
                        <div class="row">
                            <div class="col-md-8 col-md-offset-3">
                                <input type="button" id="btnReset" value="Reset" onclick="Reset();" class="btn btn-default" />
                                <input type="submit" value="Save" class="btn btn-primary" />
                            </div>
                        </div>
                    </div>
                </div>
                }

            </div>
        </div>
    </div>
</div>
<script type="text/javascript">
    function Reset() {
        document.getElementById('ddlCountry').selectedIndex = 0;
        document.getElementById('ddlState').innerHTML = "";
        document.getElementById('ddlCity').innerHTML = "";


        $(function () {
            $('#ddlCountry').change(function () {
                $.ajax({
                    type: "post",
                    url: "/Addresses/GetStates",
                    data: { countryId: $('#ddlCountry').val() },
                    datatype: "json",
                    traditional: true,
                    error: function (_, err) {
                        console.log(_, err)
                    },
                    success: function (data) {
                        $.each(data, function (index, value) {
                            $('#ddlState').append('<option value="' + value.StateId + '">' + value.StateName + '</option>');
                        });
                    }
                });
            });

            $('#ddlState').change(function () {
                $.ajax({
                    type: "post",
                    url: "/Addresses/GetCities",
                    data: { stateId: $('#ddlState').val() },
                    datatype: "json",
                    traditional: true,
                    error: function (_, err) {
                        console.log(_, err)
                    },
                    success: function (data) {
                        $.each(data, function (index, value) {
                            $('#ddlCity').append('<option value="' + value.CityId + '">' + value.CityName + '</option>');
                        });
                    }
                });
            });
        });
    }

</script>

Это рабочее решение.Однако в идеальном мире не было бы четкой кнопки.Так что в будущем я буду работать, чтобы найти способ избавиться от этого.Надеюсь, что это поможет кому-то, нуждающемуся в простом способе редактирования и просмотра текущих значений каскадных выпадающих списков

0 голосов
/ 10 декабря 2018

С такой ситуацией я сталкивался раньше.и я решил это таким образом!используя viewModel.В приведенном выше примере типом является модель домена, имеющая несколько значений в базе данных.в режиме редактирования я просто инициализирую viewModel в методе Action и передаю его в представление.

   public ActionResult Edit(int id)
            {
                Customer customer = _context.Customers.SingleOrDefault(x => x.Id == id);
                if (customer == null)
                    return HttpNotFound();

                CustomerViewModel viewModel = new CustomerViewModel()
                {
                    Customer = customer,
                    Type = _context.Type
                };

                return View("Customer_Form", viewModel);
            }

альтернативный вид для выпадающего списка будет.

@Html.DropDownListFor(m => m.Customer.Type , new SelectList(Model.Type , "Id", "Name"), "Select Type", new { @class = "form-control" })
        @Html.ValidationMessageFor(m => m.Customer.Type )

Type Class.

public class Type
{
    public int Id { get; set; }
    public string typeName { get; set; }
}

Тип ViewModel.

public class CustomerViewModel
{
    public IEnumerable<Type> Types { get; set; }
    public Customer Customer { get; set; }
}

Надеюсь, мой ответ будет полезен!для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...