在html表单中有大量的模型绑定示例,但我想知道它是否可能,如果是这样,如何使用ActionLinks/GET请求的模型绑定.
所以,给出以下模型
public class Lurl
{
public string Str {get;set;}
public char Chr {get;set;}
public double Dbl {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
和以下路线(我不确定这将如何形成;我提出它以显示我希望URL如何呈现属性Str,Chr和Dbl)
routes.MapRoute(
"LurlRoute",
"Main/Index/{str}/{chr}/{dbl}",
new
{
controller = "Main",
action = "Index",
lurl = (Lurl)null
}
);
Run Code Online (Sandbox Code Playgroud)
我想在我的Controller中以这种方式使用它
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index(Lurl lurl)
{
/* snip */
}
Run Code Online (Sandbox Code Playgroud)
这种方式在我的页面中(两种可能的选择;还有更多吗?)
<div class="links">
<%Html.ActionLink("Link one", "Index", new { lurl = Model })%><br />
<%Html.ActionLink("Link two", "Index",
new { str = Model.Str, chr = Model.Chr, dbl = Model.Dbl })%>
</div>
Run Code Online (Sandbox Code Playgroud)
这可能与模型绑定基础结构有关吗?如果是这样,我的样品需要做些什么才能使它们起作用?
我在提交多个模型的表单上遇到问题.我有一份投诉表格,其中包括投诉信息以及一对多投诉人.我正在尝试提交表单,但我在绑定上遇到错误.ModelState.IsValid始终返回false.
如果我调试并查看ModelState错误,我得到一个说法:"EntityCollection已经被初始化.应该只调用InitializeRelatedCollection方法在对象图的反序列化期间初始化一个新的EntityCollection".
此外,在调试时,我可以看到投诉模型确实填写了表单提交中的投诉人,因此似乎该部分正在运行.
我不确定使用默认的ModelBinder我是不是可以做什么,或者我是不是以正确的方式去做.我似乎无法找到任何具体的例子或文件.这里可以在stackoverflow上找到一个非常类似的问题,但它似乎并不处理强类型视图.
控制器代码:
public ActionResult Edit(int id)
{
var complaint = (from c in _entities.ComplaintSet.Include("Complainants")
where c.Id == id
select c).FirstOrDefault();
return View(complaint);
}
//
// POST: /Home/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Complaint complaint)
{
if (!ModelState.IsValid)
{
return View();
}
try
{
var originalComplaint = (from c in _entities.ComplaintSet.Include("Complainants")
where c.Id == complaint.Id
select c).FirstOrDefault();
_entities.ApplyPropertyChanges(originalComplaint.EntityKey.EntitySetName, complaint);
_entities.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
Run Code Online (Sandbox Code Playgroud)
查看代码(这是由创建/编辑视图调用的部分视图,它也是使用Complaint强类型的):
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ProStand.Models.Complaint>" %>
<%= …Run Code Online (Sandbox Code Playgroud) 我正在使用Knockout js.我有一个包含对象数组的视图模型,我希望允许用户使用向导样式界面编辑其中一个对象.我遇到的问题是向导将根据所做的选择显示不同的步骤.例如:
这样下去,通过向导的路径不是线性的.
我的问题是我在启动时将所有可能的向导UI步骤绑定到视图模型,即使某些步骤永远不会显示并且某些屏幕上的绑定将无效(例如,步骤5可能绑定到viewModel.theObject.PropertyA. PropertyB.PropertyC()但在步骤1中PropertyB仍然为null.
一个更好的方法可能是在显示它们时绑定到UI步骤,但我的问题就在那里我不知道一旦步骤完成就"取消绑定"模型的好方法所以我最终可能会遇到步骤绑定到原始列表中的多个对象!
Darin Dimitrov的答案包含另一个相关问题的链接.该页面上提出的解决方案之一最终为我们工作.
下面的代码示例在MVC 2中工作但在MVC 3中引发异常.有谁知道为什么MVC 3引入了这个突破性的变化?有没有办法让这个在MVC 3中工作,同时还允许我在视图中将视图模型描述为一个接口?
StackOverflow上还有另一个相关的问题,但它没有给我任何关于为什么MVC 2和MVC 3之间存在差异的信息.
模型
public interface IPerson {
string Name { get; set; }
}
public interface ISpy : IPerson {
string CodeName { get; set; }
}
public class Spy : ISpy {
public string Name { get; set; }
public string CodeName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
控制器动作
public ActionResult Index() {
var model = new Spy { Name = "James Bond", CodeName = "007" …Run Code Online (Sandbox Code Playgroud) TL; DR:在我的ASP.NET MVC3应用程序中,我应该如何实现一个允许我在"子"实体列表的详细信息的同时编辑"父"实体的详细信息的视图?
更新:我接受了@ torm的答案,因为他提供了一个链接,可以解释为什么我当前的解决方案可能会有所改善.但是,如果有其他人有任何选择,我们很乐意听到!
我一直在寻找和阅读(到目前为止的一些调查结果,请参见底部的"参考文献"部分).然而,我仍然觉得到目前为止我找到的解决方案有点"臭".我想知道你们中是否有人有更优雅的答案或建议(或者可以解释为什么这可能会"变得如此好").提前致谢!
所以,这是设置:
public class Wishlist
{
public Wishlist() { Wishitems = new List<Wishitem>(); }
public long WishListId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Wishitem> Wishitems { get; set; }
}
public class Wishitem
{
public long WishitemId { get; set; }
public string Name { get; set; }
public int Quantity { …Run Code Online (Sandbox Code Playgroud) 我最近开始使用MVC而且我很少失望.框架正在阻碍我,而不是帮助我.
我正在尝试编写这样的控制器动作(伪代码)
ActionResult Save(long id, string whichForm)
{
if (whichForm == "A")
{
var vm = CreateModel(Request.Form);
if (!TryValidate(vm))
return View(vm);
else
return RedirectToRoute("Success");
}
else ....
}
Run Code Online (Sandbox Code Playgroud)
基本上我想控制构建视图模型的时间以及何时验证它.这可能吗?如何实现CreateModel方法?考虑我可能想在此控制器操作中创建几个不同的视图模型.
*Rant:我真的不明白为什么在DefaultModelBinder中将视图模型绑定和验证混合在一起.好像代码味道.特别是当它很难覆盖这种行为时.
我有一个BookCreateModel,它包含书籍的平面信息,例如Title,PublishYear&etc以及书籍作者集合(复杂类型):
public class BookCreateModel
{
public string Title { get; set; }
public int Year { get; set; }
public IList<AuthorEntryModel> Authors { get; set; }
}
public class AuthorEntryModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在CreateBook视图中我使用了EditorForhelper:
@Html.EditorFor(m => m.Authors, "AuthorSelector")
Run Code Online (Sandbox Code Playgroud)
和AuthorSelector模板如下:
<div class="ptr_authors_wrapper">
@for (int i = 0; i < Model.Count; i++)
{
<div class="ptr_author_line" data-line-index="@i">
@Html.TextBoxFor(o => o[i].FirstName)
@Html.TextBoxFor(o => o[i].LastName)
</div>
}
</div>
<script> …Run Code Online (Sandbox Code Playgroud) 我发布带有下划线(like_this)的变量名称的json 并尝试绑定到camelcased(LikeThis)的模型,但是这些值无法绑定.
我知道我可以写一个自定义模型绑定器,但由于强调的约定是如此常见,我希望已经存在一个解决方案.
我试图发布的动作/模型是:
/* in controller */
[HttpPost]
public ActionResult UpdateArgLevel(UserArgLevelModel model) {
// do something with the data
}
/* model */
public class UserArgLevelModel {
public int Id { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public int ArgLevelId { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
和json数据是这样的:
{
id: 420007,
first_name: "Marc",
surname: "Priddes",
arg_level_id: 4
}
Run Code Online (Sandbox Code Playgroud)
(不幸的是我不能改变json或模型的命名)
我的web项目中有一个类:
public class MyClass
{
public int? Param1 { get; set; }
public int? Param2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是我的控制器方法中的参数:
public ActionResult TheControllerMethod(MyClass myParam)
{
//etc.
}
Run Code Online (Sandbox Code Playgroud)
如果我使用POST调用方法,模型绑定会自动生效(我在js侧使用angular,这可能无关紧要):
$http({
method: "post",
url: controllerRoot + "TheControllerMethod",
data: {
myParam: myParam
}
}).success(function (data) {
callback(data);
}).error(function () {
alert("Error getting my stuff.");
});
Run Code Online (Sandbox Code Playgroud)
如果我使用GET,则控制器中的参数始终为null.
$http({
method: "get",
url: controllerRoot + "TheControllerMethod",
params: {
myParam: myParam
}
}).success(function (data) {
callback(data);
}).error(function () {
alert("Error getting my stuff.");
});
Run Code Online (Sandbox Code Playgroud)
使用默认模型绑定器的复杂模型绑定是否仅适用于POST,或者我可以做些什么来使其与GET一起工作?
这主要是对本期评论的后续评论,但我没有足够的声誉评论......
假设我有一个简单的模型:
public class SimpleClass
{
public String Label { get; set; }
public String FirstName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
标签是基于用户/客户端更改的,因此它不能是DataAttribute.如果发布回发处理问题时,我们需要重绘整个页面.这是前一篇文章的关键问题.接受的解决方案是这样做:
@Html.DisplayTextFor(model => model.Label)
@Html.HiddenFor(model => model.Label)
@Html.EditorFor(model => model.FirstName)
Run Code Online (Sandbox Code Playgroud)
这是有道理的,因为它有效.但是我们的模型更加复杂和广泛.这种方法会导致大量的隐藏字段,这似乎是一个非常肮脏的解决方案.
这让我想到JP的评论:
解决方案是重新加载模型.但它不仅仅是重新加载,它也是一种合并,因为您希望保留任何客户端数据更改.
default: SimpleClass { Label="TheLabel", FirstName="Rob"}
postedback: SimpleClass { Label="", FirstName="Steve" }
we want: SimpleClass { Label="TheLabel", "FirstName="Steve" }
Run Code Online (Sandbox Code Playgroud)
我的问题是MVC有一个很好的方法来知道哪些字段被回发,所以它正确合并?我们只需要合并回传字段而不是空白属性.
或者只是更好地整理回发而不是表单提交?这样可以避免提交时出现所有模型重新加载问题.
为了给予Pablo信用,我接受了他的解决方案.要查看我的解决方案的简单示例,请在下面的答案中查看Robert Harvey的评论:
model-binding ×10
asp.net-mvc ×7
c# ×5
javascript ×2
angularjs ×1
editorfor ×1
html-helper ×1
http-get ×1
json ×1
knockout.js ×1
mvvm ×1
razor ×1
wizard ×1