【问题标题】:MVC: DropdownListFor error "cannot convert lambda expression to type 'string' because it is not a delegate type"MVC:DropdownListFor 错误“无法将 lambda 表达式转换为类型‘字符串’,因为它不是委托类型”
【发布时间】:2016-07-26 12:04:00
【问题描述】:

我有以下问题。

我有一个名为Users 的表,我还有另一个名为Department 的表。

现在我希望,在 UI 中,当用户要使用用户表单创建自己作为用户时,他会在部门字段中获得一个下拉列表,列出部门表中可用的所有部门标题。原因:部门表将用于其他操作,不应与用户数据链接。所以 Userdata 应该只包含表中的部门名称,这就足够了。

我的控制器如下所示:

public ActionResult UserCreate()
{
    ViewBag.AppDataDepartment = new SelectList(database.department, "department_title", "department_title");
    return View();
}

[HttpPost]
public ActionResult UserCreate(Users user)
{
    if (user.UserID == "" || user.UserID == null)
    {
        ModelState.AddModelError(string.Empty, "UserID cannot be blank");
    }
    try
    {
        if (ModelState.IsValid)
        {
            List<string> results = database.Database.SqlQuery<String>(string.Format("SELECT UserID FROM USERS WHERE UserID = '{0}'", user.UID)).ToList();
            bool _userExistsInTable = (results.Count > 0);
            Users _user = null;
            if (_userExistsInTable)
            {
                _user = database.Users.Where(p => p.UserID == user.UserID).FirstOrDefault();
                if (_user != null)
                {
                   if(_user.active == true)
                    { 
                            ModelState.AddModelError(string.Empty, "USER already exists!");
                    }
                    else
                    {
                        database.Entry(_user).Entity.active = true;
                        database.Entry(_user).Entity.Last_Modified = System.DateTime.Now;
                        database.Entry(_user).State = EntityState.Modified;
                        database.SaveChanges();
                        return RedirectToAction("Index");
                    }
                }
            }
            else
            {
                _user = new Users();
                _user.UserID = user.UserID;
                _user.lastname = user.lastname;
                _user.firstname = user.firstname;
                _user.mail = user.mail;
                _user.department = user.department;
                _user.user_image = user.user_image;
                _user.image_path = user.image_path;
                 if (ModelState.IsValid)
                 {
                    _user.active = true;
                    _user.Last_Modified = System.DateTime.Now;
                    database.Users.Add(_user);
                    database.SaveChanges();
                    ViewBag.AppDataDepartment = new SelectList(database.department, "department_title", "department_title");
                    return RedirectToAction("Index");
                }
            }
        }
    }
    catch (Exception ex)
    {
        //return base.ShowError(ex);
    }
    return View(user);
}

这是我的 HTML 部分:

<div class="row">
    @Html.LabelFor(model => model.UserID, "UserID", new { @class = "col-sm-2 control-label" })
    <div class="col-md-4">
        @Html.TextBoxFor(model => model.UserID, new { @class = "col-md-4 control-label form-control", @id = "inputEmail3" })
    </div>

    @Html.LabelFor(model => model.department, "Department", new { @class = "col-sm-2 control-label" })
    <div class="col-md-4">
        @Html.DropDownList(model => model.department, (SelectList) ViewBag.AppDataDepartment, htmlAttributes: new { @class = "form-control" })
    </div>
</div>

最后是我的系类:

[Table("department")]
public partial class department
{
    [Key]
    public int departmentid { get; set; }
    [Required]
    public string department_title { get; set; }
    public string subdepartment { get; set; }
}

但我无法编译,因为我得到了错误:

错误 CS1660 无法将 lambda 表达式转换为类型“字符串”,因为 它不是一个委托类型 BTKPI

为什么这不起作用?我该如何解决?

我已经看过这个SolutionProposal,但这没有帮助,因为模型、Linq 和 Data.Entity 已经被引用了。

【问题讨论】:

  • @Html.DropDownListFor() 不是@Html.DropDownList()
  • @StephenMuecke 谢谢,但随后我收到以下错误消息:错误 CS1928 'HtmlHelper' 不包含 'DropDownListFor' 的定义和最佳扩展方法重载 'SelectExtensions.DropDownListFor(HtmlHelper, Expression>, IEnumerable, object)' 有一些无效参数
  • 你有这么多糟糕的代码,难怪能正常工作。你绑定的模型是什么? (您所显示的只是class department,但不包含名为department 的属性)
  • @StephenMuecke 哦,好的,现在可以了,我又写了选择列表。我正在尝试其他东西,因此我将其删除。但永远不会少,非常感谢。但是为了在编码方面变得更好(我对这个话题真的很陌生),是什么让我的代码变得糟糕?我怎样才能改进它,以获得好的代码?
  • 太多了,无法一一列举。不过明天我会给你一些学习链接。

标签: c# asp.net-mvc entity-framework model-view-controller lambda


【解决方案1】:

必须是DropDownListFor(),而不是DropDownList()

@Html.DropDownListFor(m => m.department, (SelectList)ViewBag.AppDataDepartment, new { @class = "form-control" })

如果你要使用DropDownList(),那就是

@Html.DropDownList("department", (SelectList)ViewBag.AppDataDepartment, new { @class = "form-control" })

但是,您的代码还有许多其他问题需要解决。

  1. 你的控制器应该是UserController和方法Create() 这样 url 将是 ../User/Create,而不是 User/UserCreate
  2. 您正在编辑数据,因此您应该使用视图模型(不要使用 编辑数据时的数据模型) - 参考What is ViewModel in MVC?, 并且视图模型应该包含一个属性 IEnumerable&lt;SelectListItem&gt; DepartmentList - 一个典型的例子是 显示在this question/answer
  3. 您的Users 表应该存储IDDepartment, 不是它的名字,并且应该与 Departments 表。
  4. UserID 的视图模型属性应该有一个[Required] 属性和视图应该包含 @Html.ValidationMesageFor(m => m.UserID) 以便您获得客户端和服务器端验证(DepartmentID 属性也是如此)。你还应该 考虑将RemoteAttribute 应用于UserID 属性,所以 你得到客户端验证 - 参考How to: Implement Remote Validation in ASP.NET MVC

最后,您的 POST 方法几乎没有什么意义。您调用数据库两次以检查用户是否已经存在。您多次检查ModelState.IsValid。您的user_imageimage_path 属性建议您需要上传图片,但您无法将其保存在任何地方。您分配ViewBag.AppDataDepartment,然后立即重定向到Index() 方法。您的代码应该类似于(忽略文件上传问题)

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(UserVM model)
{
    // Return early
    if (!ModelState.IsValid)
    {
        // You will enter this automatically of UserID is null
        model.DepartmentList = ... // assign the SelectList
        return View(model);
    }
    // One database call to check if the user exists
    User user = database.Users.Where(p => p.UserID == model.UserID).FirstOrDefault();
    if (user != null && !user.active)
    {
        user.active = true;
        // Save and redirect
    }
    else if (user != null)
    {
        ModelState.AddModelError(string.Empty, "USER already exists!");
        model.DepartmentList = ... // assign the SelectList
        return View(model);
    }
    user = new User
    {
        UserID = model.UserID,
        lastname = model.lastname,
        .... // set other properties of User
        Last_Modified = System.DateTime.Now
    }
    // Save and redirect
}

虽然不清楚为什么已存档的现有用户需要导航到Create() 方法(并被呈现一个表单以填写他们之前已经输入的大量详细信息)。您应该有一个单独的方法来激活以前存档的用户。

【讨论】:

  • 其实这是管理员用户控制。我已经实现了一个 RBAC 模型,它具有角色、权限和用户。它们都在 Controller Admin 中。这就是为什么我有像 CreateUser 这样的操作名称,因为我也有 CreateRole 和 CreatePermission。您发布的链接非常有帮助。
  • 那么你应该使用Areas
  • 谢谢,这听起来很合乎逻辑。我今天将尝试实现它:) 感谢您的帮助和链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多