从表格中的asp.net MVC中的数据库填充下拉列表

时间:2017-11-24 20:37:20

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

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

我有一个页面,我需要显示一个包含数据库值的下拉列表(显示名称,但保持键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>

...

我知道View中不能有多个模型。我知道可能必须创建一个包含所有参数的Combined类,但我不知道如何从DataTable填充List(或者可能是带有Key和Value的Dictionary?!?)并在下拉列表中显示Value,并且将密钥传递给Controller-&gt; ActionResult AddOffer [httpPost]中的参数subTypeId。

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

谢谢,并希望不会收到太多负面投票:D

2 个答案:

答案 0 :(得分:0)

您可以向视图模型添加2个属性,其中一个属性为List<SelectListItem>,以传递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个属性,一个用于列表,一个用于选定值,并填充list属性并使用DropDownListFor帮助程序。

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

答案 1 :(得分:0)

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

public class AddOfferViewModel
{

   public AddOfferAnnounceModel Model {get;set;}

   public SelectList AnnouncementTypeSelectList {get;set;}

   public AddOfferViewModel()
   {
       Model = new AddOfferAnnounceModel();
   }

}

现在在Add Offer的Add动作中,你必须编写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<AnnouncementType>,然后在DropDownListFor方法调用内部创建SelectList内联。

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

public SelectList AnnouncementTypeSelectList {get;set;}

with:

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);
    }
}

并在View for create下拉列表中,它将是以下行:

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

希望它有帮助!