Asp.net mvc MVC ASP.NET 2-项目数组向导
我想要一点建议。我是MVC新手,一直在尝试编写一个使用web服务获取数据的示例应用程序。正在从Microsoft Navision数据库返回数据。 我希望整合的一个屏幕是一个向导,它允许用户在项目列表中来回移动,并在通过公开的web服务提交回数据库之前整理所有修改。 我的想法是尽量减少web服务调用 我一直在关注Steven Sandersons-Pro ASP.NET MVC 2 Framework一书,他有一节介绍了向导、序列化和反序列化各种控件中的对象,但在我的例子中,我希望调用同一个控制器,但可能使用不同的索引号来显示正确的项目记录。视图将具有对列表的强类型引用 请你告诉我这是不是一个正确的方法,或者这是否真的是可能的 非常感谢 pf79Asp.net mvc MVC ASP.NET 2-项目数组向导,asp.net-mvc,Asp.net Mvc,我想要一点建议。我是MVC新手,一直在尝试编写一个使用web服务获取数据的示例应用程序。正在从Microsoft Navision数据库返回数据。 我希望整合的一个屏幕是一个向导,它允许用户在项目列表中来回移动,并在通过公开的web服务提交回数据库之前整理所有修改。 我的想法是尽量减少web服务调用 我一直在关注Steven Sandersons-Pro ASP.NET MVC 2 Framework一书,他有一节介绍了向导、序列化和反序列化各种控件中的对象,但在我的例子中,我希望调用同一个控制
更新 谢谢你的回答,但我想我已经找到了答案。我试图将它保留在服务器端,因为我可能在Windows6移动设备上使用它,而且我以前也没有真正使用过javascript 通过结合使用TempData和序列化,我能够实现这一点。不确定这是否是“最佳实践”。任何关于如何改进的建议都将不胜感激 我有一个项目类
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
然后,我有一个webservice调用,它将从控制器类中的另一个方法返回一个项列表
public ActionResult GetDetails()
{
//Test filling List. Will be retrieved from Web Service eventually.
testItemList = new List<Item>();
testItemList.Add(new Item() { Id = 1, Name = "Bike", Price = new decimal(1000) });
testItemList.Add(new Item() { Id = 2, Name = "Wheel", Price = new decimal(99.99) });
testItemList.Add(new Item() { Id = 3, Name = "Saddle", Price = new decimal(49.99) });
TempData["itemList"] = testItemList;
return RedirectToAction("Details");
}
控制器
[HttpGet]
public ActionResult Details()
{
testItemList = (IList<Item>)TempData["itemList"];
currentIndex = (int)TempData["currIndex"];
return View(testItemList[currentIndex]);
}
[HttpPost]
public ActionResult Details(string next, string back)
{
var testItem = testItemList[currentIndex];
if (TryUpdateModel(testItem))
{
if (next != null)
{
currentIndex = (currentIndex + 1) == testItemList.Count ? currentIndex : currentIndex + 1;
}
if (back != null)
{
currentIndex = (currentIndex - 1) < 0 ? currentIndex : currentIndex - 1;
}
TempData["currIndex"] = currentIndex;
TempData["itemList"] = testItemList;
return RedirectToAction("Details");
}
TempData["currIndex"] = currentIndex;
TempData["itemList"] = testItemList;
return View(testItem);
}
[HttpGet]
公众行动结果详情()
{
testItemList=(IList)TempData[“itemList”];
currentIndex=(int)TempData[“currentIndex”];
返回视图(testItemList[currentIndex]);
}
[HttpPost]
公共操作结果详细信息(下一个字符串,下一个字符串)
{
var testItem=testItemList[currentIndex];
if(TryUpdateModel(testItem))
{
如果(下一步!=null)
{
currentIndex=(currentIndex+1)=testItemList.Count?currentIndex:currentIndex+1;
}
如果(返回!=null)
{
currentIndex=(currentIndex-1)<0?currentIndex:currentIndex-1;
}
TempData[“currIndex”]=当前索引;
TempData[“itemList”]=testItemList;
返回重定向操作(“详细信息”);
}
TempData[“currIndex”]=当前索引;
TempData[“itemList”]=testItemList;
返回视图(testItem);
}
然后在视图上,我序列化列表和当前索引,以便跟踪它
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
var listSerialized = Request.Form["itemList"];
if (listSerialized != null)
{
testItemList = (IList<Item>)new MvcSerializer().Deserialize(listSerialized);
}
var indexSerialized = Request.Form["currIndex"];
if (indexSerialized != null)
{
currentIndex = (int)new MvcSerializer().Deserialize(indexSerialized);
}
else
{
currentIndex = 0;
}
}
受保护的覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
{
var listSerialized=Request.Form[“itemList”];
if(listSerialized!=null)
{
testItemList=(IList)新的MvcSerializer()。反序列化(listSerialized);
}
var indexSerialized=Request.Form[“currendex”];
如果(indexSerialized!=null)
{
currentIndex=(int)新的MvcSerializer()。反序列化(indexSerialized);
}
其他的
{
currentIndex=0;
}
}
看法
细节
细节
t、 名称)%%>
t、 价格)%>
这在很大程度上取决于表单的复杂性,以及如果用户需要一半填写表单,然后下次再来,是否需要存储临时数据并可能进行保存
我个人喜欢使用各种可用的客户端向导。虽然不是用于向导,但可以用于向导。这有几个优点:
- 通话次数限制为最后一次通话,用户可以根据自己的意愿进行任意修改。因此,在web服务调用方面是最佳的
- 更好地支持服务器端技术,如ASP NET MVC
- 它可以通过简单的实现来保存半填充的表单
但它需要非常好的客户端验证,以尽量减少由于无效日期而产生的往返,但现在有几十种工具可供您选择,以实现健壮的客户端验证。如果您确实需要服务器端向导,请尝试以下方法: 假设您有一个将在向导完成时填充的模型
// This is a pseudo-model to show the properties Member has in this example.
// I use entity framework when generating my model objects. How you generate
// your model objects is not important in this example.
public class Member
{
public string Username { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string ReferredBy { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
我建立了一个名为Member
的简单模型,我们的向导最终将填充该模型。现在,我将构建一个视图模型,用于向导页面
public class RegisterViewModel
{
public Member NewMember { get; set; }
public int Step { get; set; } //int cannot be null and will be 0 by default.
}
现在我要建立一些行动方法
// First request will pull up the first view of the wizard with
// a new RegisterViewModel.
[HttpGet]
public ViewResult RegisterNewMember()
{
return View("RegisterWizardStep1", new RegisterViewModel());
}
// This will be the post action method. Rather than create a different
// action method for every step of the wizard, our view model will support
// which step we are on and this method will be aware of what to do.
[HttpPost]
public ViewResult RegisterNewMember(RegisterViewModel viewModel)
{
if (ModelState.IsValid)
{
if (viewModel.Step < 2)
return View(String.Format("RegisterWizardStep{0}", viewModel.Step + 1), viewModel);
else
{
db.Members.AddObject(viewModel.NewMember);
db.SaveChanges();
// db is a fictional context. The syntax is that of entity framework.
// You could substitute this for a LINQ to SQL context or any other
// data storage component.
ViewBag.WelcomeMessage = "Thank you for registering. We welcome you!";
return View("Welcome");
}
}
else
return View(String.Format("RegisterWizardStep{0}", viewModel.Step));
// Assuming you have model validation set up, returning the same view with
// an invalid modelstate will trigger your validation helpers.
}
//第一个请求将使用
//一个新的RegisterViewModel。
[HttpGet]
公共视图结果注册表成员()
{
返回视图(“RegisterWizardStep1”,newRegisterViewModel());
}
//这将是操作后的方法。而不是创造一个不同的
//对于向导的每个步骤,我们的视图模型都将支持
//我们正在进行哪一步,这种方法将知道该做什么。
[HttpPost]
公共视图结果RegisterNewMember(RegisterViewModel视图模型)
{
if(ModelState.IsValid)
{
如果(viewModel.Step<2)
返回视图(String.Format(“RegisterWizardStep{0}”、viewModel.Step+1)、viewModel);
其他的
{
db.Members.AddObject(viewModel.NewMember);
db.SaveChanges();
//db是一个虚构的上下文,语法是实体框架的语法。
//您可以将其替换为LINQ到SQL上下文或任何其他上下文
//数据存储组件。
ViewBag.WelcomeMessage=“感谢您的注册。我们欢迎您!”;
返回视图(“欢迎”);
}
}
其他的
返回视图(String.Format(“RegisterWizardStep{0}”,viewModel.Step));
//假设已设置模型验证,则返回相同的视图
//无效的modelstate将触发验证帮助程序。
}
在这个例子中,我需要三个步骤
public class RegisterViewModel
{
public Member NewMember { get; set; }
public int Step { get; set; } //int cannot be null and will be 0 by default.
}
// First request will pull up the first view of the wizard with
// a new RegisterViewModel.
[HttpGet]
public ViewResult RegisterNewMember()
{
return View("RegisterWizardStep1", new RegisterViewModel());
}
// This will be the post action method. Rather than create a different
// action method for every step of the wizard, our view model will support
// which step we are on and this method will be aware of what to do.
[HttpPost]
public ViewResult RegisterNewMember(RegisterViewModel viewModel)
{
if (ModelState.IsValid)
{
if (viewModel.Step < 2)
return View(String.Format("RegisterWizardStep{0}", viewModel.Step + 1), viewModel);
else
{
db.Members.AddObject(viewModel.NewMember);
db.SaveChanges();
// db is a fictional context. The syntax is that of entity framework.
// You could substitute this for a LINQ to SQL context or any other
// data storage component.
ViewBag.WelcomeMessage = "Thank you for registering. We welcome you!";
return View("Welcome");
}
}
else
return View(String.Format("RegisterWizardStep{0}", viewModel.Step));
// Assuming you have model validation set up, returning the same view with
// an invalid modelstate will trigger your validation helpers.
}
// RegisterWizardStep0
@model AppName.Models.RegisterNewMember
@using AppName.Models;
@{
Layout = "~/Views/Shared/Master.cshtml";
}
@* I'm not going to worry much about formatting in these views as they are only samples.
I am also not going to worry about client-side validation before step submission;
I will let you worry about that. *@
@using(Html.BeginForm())
{
<text>
@Html.HiddenFor(x => x.Step)
@Html.TextBoxFor(x => x.NewMember.Username)
@Html.ValidationMessageFor(x => x.NewMember.Username)
<br />
@Html.TextBoxFor(x => x.NewMember.FirstName)
@Html.ValidationMessageFor(x => x.NewMember.FirstName)
<br />
@Html.TextBoxFor(x => x.NewMember.LastName)
@Html.ValidationMessageFor(x => x.NewMember.LastName)
<br />
<input type="submit" value="Next" />
</text>
}
// RegisterWizardStep1
@model AppName.Models.RegisterNewMember
@using AppName.Models;
@{
Layout = "~/Views/Shared/Master.cshtml";
}
@using(Html.BeginForm())
{
<text>
@Html.HiddenFor(x => x.Step)
@Html.HiddenFor(x => x.Member.Username)
@Html.HiddenFor(x => x.NewMember.FirstName)
@Html.HiddenFor(x => x.NewMember.LastName)
@Html.TextBoxFor(x => x.NewMember.Email)
@Html.ValidationMessageFor(x => x.NewMember.Email)
<br />
@Html.TextBoxFor(x => x.NewMember.ReferredBy)
@Html.ValidationMessageFor(x => x.NewMember.ReferredBy)
<br />
<input type="submit" value="Next" />
</text>
}
// RegisterWizardStep2
@model AppName.Models.RegisterViewModel
@using AppName.Models;
@{
Layout = "~/Views/Shared/Master.cshtml";
}
@using(Html.BeginForm())
{
<text>
@Html.HiddenFor(x => x.Step)
@Html.HiddenFor(x => x.NewMember.Username)
@Html.HiddenFor(x => x.NewMember.FirstName)
@Html.HiddenFor(x => x.NewMember.LastName)
@Html.HiddenFor(x => x.NewMember.Email)
@Html.HiddenFor(x => x.NewMember.ReferredBy)
@Html.TextBoxFor(x => x.NewMember.Address)
@Html.ValidationMessageFor(x => x.NewMember.Address)
<br />
@Html.TextBoxFor(x => x.NewMember.City)
@Html.ValidationMessageFor(x => x.NewMember.City)
<br />
@Html.TextBoxFor(x => x.NewMember.State)
@Html.ValidationMessageFor(x => x.NewMember.State)
<br />
@Html.TextBoxFor(x => x.NewMember.Country)
@Html.ValidationMessageFor(x => x.NewMember.Country)
<br />
<input type="submit" value="Done" />
</text>
}