我有一个用Razor编写的下拉列表,用于我正在处理的MVC应用程序:
@Html.DropDownList("BillId", "")
但是,用户不必根据我的程序逻辑选择任何内容(列表中填充了控制器中的“Bill”对象)。如果他们没有选择任何东西我会收到错误
The ViewData item that has the key 'BillId' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'.
如果没有选择任何内容,如何在Razor中写一个语句来返回BillId为0?
我不确定语法,因为我在直接java和VB中有背景但是
If DropdownBox.SelectedIndex = 0
Else
BillId = DropdownBox.SelectedIndex
End
控制器如下:
Function Create(id As Integer) As ViewResult
ViewBag.id = id
Dim job As Job = New Job
job.CustomerId = id
job.JobAmount = 0
job.JobDate = Date.Now()
job.JobStatus = "Active"
Dim BillList = New List(Of Bill)()
Dim BillQuery = From s In db.Bills
Select s
BillList.AddRange(BillQuery)
ViewBag.BillIdList = New SelectList(BillList, "BillId", "BillDate")
ViewBag.BillId = New SelectList(BillList, "BillId", "BillDate")
Return View(job)
End Function
创建的POST功能如下:
<HttpPost()>
Function Create(job As Job) As ActionResult
If ModelState.IsValid Then
db.Jobs.Add(job)
db.SaveChanges()
Dim customer As Customer = db.Customers.Find(job.CustomerId)
Dim customerNumber As String = customer.CustCellphone.ToString()
Dim messageSender As SendMessage = New SendMessage
Dim smsMessage As String = "LAUNDRY: Job Number " & job.JobId & " has been booked in. You will be notified when individual services within it are ready for collection."
messageSender.SendMessage(smsMessage, customerNumber)
Dim url As String = "/RequestedService/AddService/" + job.JobId.ToString()
Return Redirect(url)
End If
Return View(job)
End Function
修改
我也想知道这是如何传回来的,因为在POST中我可以检查'null'?但是我觉得问题可能是按下提交按钮的时刻
答案 0 :(得分:1)
在您的POST控制器操作中,您忘记在返回视图之前填充ViewCrap(哎呀,我的意思是ViewBag):
<HttpPost()>
Function Create(job As Job) As ActionResult
If ModelState.IsValid Then
...
End If
' Here you must populate the ViewCrap before returning the view the same
' way you did in your GET action because your view depend on it
Dim BillQuery = From s In db.Bills
Select s
ViewBag.BillId = New SelectList(BillQuery.ToList(), "BillId", "BillDate")
Return View(job)
End Function
但我强烈建议你使用视图模型而忘记......的存在......(我不想发音的那个词)。
更新:
现在让我们看看实现它的正确方法(通过使用视图模型)。视图模型是您应为每个视图定义的类,它将表示其特定要求。因此,根据您在评论部分中所说的我的答案,您希望在视图中有一个下拉列表,用户必须从下拉列表中选择一个帐单,这是必需的。
让我们滚动视图模型:
public class JobViewModel
{
[Required(ErrorMessage = "Please select a bill")]
[Display(Name = "Bill")]
public int? SelectedBillId { get; set; }
public IEnumerable<SelectListItem> Bills
{
get
{
return db.Bills.ToList().Select(x => new SelectListItem
{
Value = x.BillId.ToString(),
Text = x.BillDate.ToString()
});
}
}
public int CustomerId { get; set; }
... here you could put any other properties that you want
to display on the view, things like JobId, ...
}
然后我们用2个动作定义我们的控制器:
public ActionResult Create(int id)
{
var model = new JobViewModel
{
CustomerId = id
};
return View(model);
}
[HttpPost]
public ActionResult Create(JobViewModel model)
{
if (ModelState.IsValid)
{
// Using AutoMapper here to map between the domain model
// and the view model (http://automapper.org/)
var job = Mapper.Map<JobViewModel, Job>(model);
// Now call your service layer to do the necessary processings
// on this job domain model including saving the job and sending
// messages and stuff. This avoids polluting your controller with
// business logic code which belongs to your service layer
ServiceLayer.ProcessJob(job);
return RedirectToAction("AddService", "RequestedService", new { id = job.JobId });
}
return View(model);
}
最后你会有一个相应的视图,它将强烈地输入到视图模型中:
@model JobViewModel
@using (Html.BeginForm())
{
<div>
@Html.LabelFor(x => x.SelectedBillId)
@Html.DropDownListFor(x => x.SelectedBillId, Model.Bills, "-- select --")
@Html.ValidationMessageFor(x => x.SelectedBillId)
</div>
... some other input fields
<p><button type="submit">OK</button></p>
}
现在,正如评论部分所承诺的那样,让我展示我所谓的绝对色情方法来解决这个问题,如果你在你的应用程序中实现,我将不得不要求你不再来返回并在StackOverflow上询问任何与ASP.NET MVC相关的问题: - )
色情方法包括手动将id = 0且text = empty string的项目插入列表的开头,然后在控制器内部验证所选的id是否等于0以便检查该模型是否有效:
所以在你的GET行动中:
Function Create(id As Integer) As ViewResult
ViewBag.id = id
Dim job As Job = New Job
job.CustomerId = id
job.JobAmount = 0
job.JobDate = Date.Now()
job.JobStatus = "Active"
Dim Bills = db.Bills.ToList().Select(Function(s) New SelectListItem With { .Value = s.BillId.ToString(), .Text = s.BillDate.ToString() })
Bills.Insert(0, New SelectListItem With { .Value = "0", .Text = "" })
ViewBag.BillId = Bills
Return View(job)
End Function
<HttpPost()>
Function Create(job As Job, BillId as Integer) As ActionResult
If BillId > 0 Then
db.Jobs.Add(job)
db.SaveChanges()
Dim customer As Customer = db.Customers.Find(job.CustomerId)
Dim customerNumber As String = customer.CustCellphone.ToString()
Dim messageSender As SendMessage = New SendMessage
Dim smsMessage As String = "LAUNDRY: Job Number " & job.JobId & " has been booked in. You will be notified when individual services within it are ready for collection."
messageSender.SendMessage(smsMessage, customerNumber)
Dim url As String = "/RequestedService/AddService/" + job.JobId.ToString()
Return Redirect(url)
End If
ModelState.AddModelError("BillId", "Please select a bill")
Return View(job)
End Function
并在视图中:
@Html.DropDownList("BillId")