我的模型形状如下:
public class GlobalSettingsViewModel
{
public List<SettingViewModel> Settings{ get;set;}
}
public class SettingViewModel
{
public string Name{ get;set;}
[Range(0,100)]
public decimal SettingValue{ get;set;}
}
我的视图为每个SettingViewModel调用Html.RenderPartial("SettingView")
。
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SettingViewModel>" %>
<% using (Html.BeginForm("Save", "GlobalSettings", FormMethod.Post))
{ %>
<table>
<tr>
<td width="150px">
<%= Html.DisplayFor(m=>m.Name) %>
</td>
<td>
<%= Html.TextBoxFor(m=>m.SettingValue) %>
</td>
<td>
<input type="submit" value="Save" class="uiButton" />
<%=Html.ValidationMessageFor(m=>m.SettingValue) %>
</td>
</tr>
</table>
<%} %>
每个SettingView
都会呈现一个回复保存操作的表单。
SettingViewModel
从表单中正确地重新水化,验证正确地确定何时生成out或range值。
我返回原始Index
视图,其中包含所需的完整GlobalSettingsViewModel
。
但是,当页面呈现每个 SettingValue的Validator时,它会显示错误消息,而不仅仅是具有不正确值的文本框?
当PartialView
是项目集合的页面时,对<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MVC.Master" Inherits="System.Web.Mvc.ViewPage<GlobalSettingsViewModel>" %>
<fieldset style="margin: 5px; width: 350px;">
<legend>Global System Settings</legend>
<div>
<%= Html.EditorFor(m => Model.Settings)%>
</div>
</fieldset>
执行服务器端验证的正确方法是什么?
所以这就是我所拥有的....它似乎有点奇怪但似乎有用......
我可以一次保存一个设置,并在发生时显示验证错误。但是我使用部分模型保存的奇怪方式似乎有些奇怪。
的Index.aspx
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SettingViewModel>" %>
<% using (Html.BeginForm("Save", "GlobalSettings", FormMethod.Post))
{ %>
<table>
<tr>
<td width="150px">
<%= Model.Name %>
</td>
<td>
<%= Html.TextBoxFor(m => m.SettingValue) %>
</td>
<td>
<input type="submit" value="Save" class="uiButton" />
</td>
</tr>
<tr>
<td colspan="3">
<%=Html.ValidationMessageFor(m=>m.SettingValue) %>
</td>
</tr>
</table>
<%= Html.HiddenFor(m => m.SettingName)%>
<%= Html.HiddenFor(m => m.Name)%>
<%} %>
SettingViewModel.ascx
public ActionResult Index()
{
var settings = GetSettings();
if (TempData["Message"] != null)
{
settings.Message = TempData["Message"].ToString();
settings.HasMessage = true;
}
return View(settings);
}
[AuthorizationFilter(true, null)]
[HttpPost]
public ActionResult Save(GlobalSettingsViewModel model)
{
if (ModelState.IsValid)
{
GlobalSettings.SetGlobalSetting(model.Settings[0].SettingName, model.Settings[0].SettingValue);
TempData["Message"] = "Saved " + model.Settings[0].Name;
return RedirectToAction("Index");
}
var settings = GetSettings();
return View("Index", settings);
}
GlobalSettingsController.cs
{{1}}
答案 0 :(得分:2)
一种可能性是使用AJAX,这样您就不必刷新整个页面。因此,您的保存操作将返回部分仅传递当前设置:
[HttpPost]
public ActionResult Save(SettingViewModel model)
{
// TODO: do some processing
return PartialView("SettingView", model);
}
然后将表单包装在一个div容器中,以便我们可以更容易地知道AJAX调用成功时要更新的部分:
<% foreach (var item in Model.Settings) { %>
<div class="setting">
<%= Html.Partial("SettingView", item) %>
</div>
<% } %>
最后在一些单独的javascript文件中AJAX化这些表单:
$(function () {
$('.setting').delegate('form', 'submit', function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
context: this,
success: function (result) {
$(this).closest('.setting').html(result);
}
});
return false;
});
});
答案 1 :(得分:1)
您的问题是RenderPartial为每个SettingsViewModel生成相同的ID。如果你查看你的渲染代码,你会发现页面中有重复的ID,而且这是无效的HTML。
您最好为SettingsViewModel使用EditorTemplate,这将具有创建唯一ID所需的逻辑。