【问题标题】:Populate dropdownlist from database in asp.net MVC in a form以表单形式从 asp.net MVC 中的数据库填充下拉列表
【发布时间】:2017-11-24 20:37:19
【问题描述】:

好的,我找到了一些类似的帖子,但是没有一点帮助我找不到解决方法(其他帖子的日期不完整)。

我有一个页面,我需要在其中显示一个包含数据库值的下拉列表(显示名称,但将键 ID 保留为值)....这个列表,以及表单的其他类型的输入。

我的模特:

public class AddOfferAnnounceModel
{
    public AnnounceTypeList AnnounceTypeList {get; set; }
    public int Surface { get; set; }
    public int SubTypeId { get; set; }

    [Required]
    public decimal Price { get; set; }

    [StringLength(200, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 0)]
    public string AnnounceDetails { get; set; }

    public bool Net { get; set; }
}

public class AnnounceTypeList
{
    public int SubTypeId { get; set; }
    public string TypeDesc { get; set; }
}

我的控制器 [httpGET] 操作(可能必须填充下拉列表:

// GET: Announce/Add new announce
    public ActionResult AddOffer()
    {
        string sql = "select typeId, typeDesc from announceTypes where parentTypeId = 1";
        using (SqlConnection cn = new SqlConnection(ConnectionString))
        {
            cn.Open();
            DataTable dt = new DataTable();
            SqlCommand cmd = new SqlCommand(sql, cn);
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            da.Fill(dt);

            var apartmentTypeList = new List<AnnounceTypeList>();
            foreach (DataRow dr in dt.Rows)
            {
                var apartmentType = new AnnounceTypeList
                {
                    SubTypeId = Convert.ToInt32(dr["TypeId"]),
                    TypeDesc = dr["TypeDesc"].ToString()
                };
                apartmentTypeList.Add(apartmentType);
            }
            return View();
        }
    }

我的控制器 [httpPOST] - 从 View 返回的所有值和要插入数据库的查询在哪里

[HttpPost]
    public ActionResult AddOffer(AddOfferAnnounceModel model)
    {
        bool isValid = true; // daca datele introduse in formularul anuntului sunt corecte si respecta regulile

        if (isValid)
        {
            string announceDetailsItem = model.AnnounceDetails;
            decimal priceItem = model.Price;
            int surfaceItem = model.Surface;
            int subTypeId = model.SubTypeId; // GETTING FROM DROPDOWNLIST !!!!
            int netItem = Convert.ToInt32(model.Net);
            DateTime dateItem = DateTime.Now;

            string sql = "insert into announces (typeid, statusId, locationId, finalPrice, date, surface, net, announceDetails) values (1, 1, 1, " + priceItem + ",'" + dateItem + "'," + surfaceItem + "," + netItem + ",'" + announceDetailsItem + "')";
                  sql += " insert into announceOfferApartments (announceId, subTypeId, yPersonTypeId) values ((select max(announceId) from announces), 6, 4)";

            using (SqlConnection cn = new SqlConnection(ConnectionString))
            {
                cn.Open();
                SqlCommand cmd = new SqlCommand(sql, cn)
                {
                    CommandType = CommandType.Text
                };
                cmd.ExecuteScalar();
                return RedirectToAction("OfferList", "Announce");
                // daca datele au fost introduse in DB, se redirectioneaza catre Lista Anunturilor
            }
        }
        return OfferList();
    }

我的观点:

@model myApp.com.Models.AddOfferAnnounceModel

...

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

    <div class="form-group">
        @Html.LabelFor(model => model.Surface, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Surface, new { htmlAttributes = new { @class = "form-control" } })
        </div>
    </div>

....

我知道一个视图中不能有多个模型。我知道可能必须创建一个包含所有参数的组合类,但我不知道我必须如何从 DataTable 填充列表(或者可能是带有键和值的字典?!?)并在下拉列表中显示值,并且在Controller->ActionResult AddOffer[httpPost]中将key传给参数subTypeId。

我需要以相同的形式创建 4 5 个下拉列表,但方法可能相同....!

谢谢,希望不要收到太多的反对票:D

【问题讨论】:

    标签: c# asp.net asp.net-mvc drop-down-menu


    【解决方案1】:

    您可以向视图模型添加 2 个属性,一个是 List&lt;SelectListItem&gt; 类型,用于传递您的 SELECT 元素所需的选项,另一个是用于选定值。

    public class AddOfferAnnounceModel
    {
        public List<SelectListItem> Items { set;get;}  // These 2 properties for the dropdown
        [Required]
        public int SelectedItem { set;get;}
    
        public int Surface { get; set; }    
        [Required]
        public decimal Price { get; set; }    
        public string AnnounceDetails { get; set; }
    
        public bool Net { get; set; }
    }
    

    现在在您的 GET 操作中,您可以创建 AddOfferAnnounceModel 的对象,填充 Items 属性并将其传递给视图。无需使用DataTable。使用 SqlReader,您只需要读取一次结果。

    public ActionResult AddOffer()
    {
       var vm = new AddOfferAnnounceModel();
       vm.Items = GetItems();
       return View(vm);
    }
    public List<SelectListItem> GetItems()
    {
        var list = new List<SelectListItem>();
        var sql = "select TypeId, TypeDesc from announceTypes where parentTypeId = 1";
        var conStr = @"yourConnectionStringGoesHere";
        using (var c = new SqlConnection(conStr))
        {
            using (var cmd = new SqlCommand(sql, c))
            {
                c.Open();
                using (var r = cmd.ExecuteReader())
                {
                    if (r.HasRows)
                    {
                        while (r.Read())
                        {
                            var t = new SelectListItem()
                            {
                                Value = r.GetInt32(r.GetOrdinal("TypeId")).ToString(),
                                Text = r.GetString(r.GetOrdinal("TypeDesc"))
                            };
                            list.Add(t);
                        }
                    }
                }
            }
        }
        return list;
    }
    

    在强类型化到AddOfferAnnounceModel 类的视图中,您可以使用Html.DropDownListFor 帮助器

    @model AddOfferAnnounceModel
    @using(Html.BeginForm())
    {
       @Html.TextBoxFor(a=>a.Price)
       @Html.TextBoxFor(a=>a.Surface)
       @Html.TextBoxFor(a=>a.AnnounceDetails)
       @Html.DropDownListFor(a=>a.SelectedItem,Model.Items)
       <input type="submit" />
    }
    

    现在在您的 HttpPost 操作中,当提交表单时,选定的选项值将在 SelectedItem 属性中

    [HttpPost]
    public ActionResult AddOffer(AddOfferAnnounceModel model)
    {
         // check model.SelectedItem and use that for saving
    }
    

    如果您有更多下拉菜单,您将执行相同的操作(添加 2 个属性,一个用于列表,一个用于选定值并填充列表属性并使用 DropDownListFor 帮助器。

    我还建议不要为您的插入查询进行字符串连接以保存新记录。这种方法容易受到 SQL 注入攻击。看看SqlParameters 以及如何使用它来为您的查询传递不同的参数。 This post 解释了处理该问题的各种方法

    【讨论】:

    • 感谢您的回复。我使用了上一篇文章中的方法。并感谢您对 sql 注入的建议......我会尽量谨慎。
    【解决方案2】:

    您实际上需要创建视图模型,该模型将保存将在下拉列表中显示的数据以及将通过HttpPost 发回的其他数据。以下是步骤。首先创建一个新类,它是 View Model:

    public class AddOfferViewModel
    {
    
       public AddOfferAnnounceModel Model {get;set;}
    
       public SelectList AnnouncementTypeSelectList {get;set;}
    
       public AddOfferViewModel()
       {
           Model = new AddOfferAnnounceModel();
       }
    
    }
    

    现在在 Add Offer 的 Get 操作中,您必须编写 ViewModel 并将其传递给 View:

    // GET: Announce/Add new announce
    public ActionResult AddOffer()
    {
        string sql = "select typeId, typeDesc from announceTypes where parentTypeId = 1";
        using (SqlConnection cn = new SqlConnection(ConnectionString))
        {
            cn.Open();
            DataTable dt = new DataTable();
            SqlCommand cmd = new SqlCommand(sql, cn);
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            da.Fill(dt);
    
            var apartmentTypeList = new List<AnnounceTypeList>();
            foreach (DataRow dr in dt.Rows)
            {
                var apartmentType = new AnnounceTypeList
                {
                    SubTypeId = Convert.ToInt32(dr["TypeId"]),
                    TypeDesc = dr["TypeDesc"].ToString()
                };
                apartmentTypeList.Add(apartmentType);
            }
    
             AddOfferViewModel viewModel = new AddOfferViewModel();
             viewModel.AnnouncementTypeSelectList  = new SelectList(apartmentTypeList,"SubTypeId","TypeDesc")
            return View(viewModel);
        }
    }
    

    现在你的视图应该是强类型的AddOfferViewModel:

    @model myApp.com.ViewwModels.AddOfferViewModel
    ...
    <div class="form-group">
            @Html.LabelFor(model => model.Model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Model.Price, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Model.Price, "", new { @class = "text-danger" })
            </div>
        </div>
    
        <div class="form-group">
            @Html.LabelFor(model => model.Model.Surface, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Model.Surface, new { htmlAttributes = new { @class = "form-control" } })
            </div>
        </div>
    

    现在您可以添加如下下拉列表:

    @Html.DropDownListFor(model=>model.Model.SubTypeId,Model.Model.AnnouncementTypeSelectList)
    

    您也可以通过其他方式执行此操作,即在 ViewModel 中添加属性以保存 List&lt;AnnouncementType&gt;,然后在 View 中的 DropDownListFor 方法调用 create SelectList 内联。

    在这种情况下,替换属性:

    public SelectList AnnouncementTypeSelectList {get;set;}
    

    与:

    public List<AnnounceTypeList> AnnouncementTypes {get;set;}
    

    在您的操作中,您只需将AnnouncementTypes 现在设置为:

    // GET: Announce/Add new announce
    public ActionResult AddOffer()
    {
        string sql = "select typeId, typeDesc from announceTypes where parentTypeId = 1";
        using (SqlConnection cn = new SqlConnection(ConnectionString))
        {
            cn.Open();
            DataTable dt = new DataTable();
            SqlCommand cmd = new SqlCommand(sql, cn);
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            da.Fill(dt);
    
            var apartmentTypeList = new List<AnnounceTypeList>();
            foreach (DataRow dr in dt.Rows)
            {
                var apartmentType = new AnnounceTypeList
                {
                    SubTypeId = Convert.ToInt32(dr["TypeId"]),
                    TypeDesc = dr["TypeDesc"].ToString()
                };
                apartmentTypeList.Add(apartmentType);
            }
    
             AddOfferViewModel viewModel = new AddOfferViewModel();
             viewModel.AnnouncementTypes = apartmentTypeList ;
            return View(viewModel);
        }
    }
    

    在用于创建下拉列表的视图中,它将是以下行:

    @Html.DropDownListFor(model=>model.Model.SubTypeId,
                                new SelectList(Model.Model.AnnouncementTypes,
                                               "SubTypeId",
                                               "TypeDesc"))
    

    希望对你有帮助!

    【讨论】:

    • 谢谢。忘记在 AddOfferAnnounceModel 类中编写构造 AnnouncementTypes :D 现在它工作完美,并将值保存在 AddOffer [httpPost]
    • 很高兴它有帮助,请随时将帖子标记为答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多