C# 使用ViewModel发布到模型中

C# 使用ViewModel发布到模型中,c#,asp.net-mvc,C#,Asp.net Mvc,我有一个模型和两个视图模型 型号: public class WebPages { [Key] public int WebPagesId { get; set; } public String DomainName { get; set; } public DateTime DomainStart { get; set; } public DateTime DomainExp { get; set; } } 视图模型: public class W

我有一个模型和两个视图模型

型号:

 public class WebPages
{
    [Key]
    public int WebPagesId { get; set; }
    public String DomainName { get; set; }
    public DateTime DomainStart { get; set; }
    public DateTime DomainExp { get; set; }
}
视图模型:

 public class WebPagesViewModel
{
    public String DomainName { get; set; }
    public DateTime DomainStart { get; set; }
    public List<SelectListItem> DurationDays { set; get; }
    public int SelectedDurationDays { set; get; }
}
控制器:

 [HttpGet]
   public async Task<ActionResult> Renewal()
   {
       var vm = new RenewalViewModel
       {
           AddTime = new List<SelectListItem>

           {
               new SelectListItem {Value = "1", Text = "1 año"},
               new SelectListItem {Value = "2", Text = "2 años"},
               new SelectListItem {Value = "3", Text = "3 años"},
               new SelectListItem {Value = "4", Text = "4 años"},
               new SelectListItem {Value = "5", Text = "5 años"},
               new SelectListItem {Value = "6", Text = "6 años"},
               new SelectListItem {Value = "7", Text = "7 años"},
               new SelectListItem {Value = "8", Text = "8 años"},
               new SelectListItem {Value = "9", Text = "9 años"}
           },
           Webpage = new SelectList(db.WebPagesList,"WebPagesId", "DomainName")
       };
        return View(vm);

    }

    [HttpPost]
    public async Task<ActionResult> Renewal(RenewalViewModel vm)
    {

        var addDays = DateTime.Now.AddYears(vm.SelectedDurationDays);

        var webpage = new WebPages
        {
          DomainExp = addDays
        };
        db.Entry(webpage).State = EntityState.Modified;

        return View(webpage);
    }
[HttpGet]
公共异步任务续订()
{
var vm=新的更新视图模型
{
AddTime=新列表
{
新建SelectListItem{Value=“1”,Text=“1 año”},
新建SelectListItem{Value=“2”,Text=“2 años”},
新建SelectListItem{Value=“3”,Text=“3 años”},
新建SelectListItem{Value=“4”,Text=“4 años”},
新建SelectListItem{Value=“5”,Text=“5 años”},
新建SelectListItem{Value=“6”,Text=“6 años”},
新建SelectListItem{Value=“7”,Text=“7 años”},
新建SelectListItem{Value=“8”,Text=“8 años”},
新建SelectListItem{Value=“9”,Text=“9 años”}
},
Webpage=新的选择列表(db.WebPagesList,“WebPagesId”,“DomainName”)
};
返回视图(vm);
}
[HttpPost]
公共异步任务续订(RenewalViewModel vm)
{
var addDays=DateTime.Now.AddYears(vm.SelectedDurationDays);
var webpage=新网页
{
DomainExp=addDays
};
db.Entry(webpage).State=EntityState.Modified;
返回视图(网页);
}
但在
返回视图(网页)我有这个问题

xxx模型。网页不可分配给模型类型xxx.Models.ViewModel.RenewalViewModel


我知道这是因为我在视图中调用了RenewalViewmodel而不是Webpages,我想知道我的错误步骤是什么,我想知道你返回的是模型,而不是ViewModel。该模型用于持久性,而ViewModel用于您的UI。如果需要UI的操作输出,则需要将其作为属性添加到ViewModel中

改变

return View(webpage);
致:

或者,如果您不想返回虚拟机:

return new HttpStatusCodeResult(HttpStatusCode.OK);

发生此错误的原因是,您的视图具有
@model RenewalViewModel
,但您向其传递了
网页的实例。要解决此错误,需要将return语句修改为

return View(vm);
但是,这只会导致更多错误,因为
List
属性的集合都是
null
。如果希望返回视图以进行更多选择,正确的方法是重定向回GET方法(即PRG模式)。但是,如果由于
ModelState
无效而需要返回视图,则需要重新分配
AddTime
Webpage
属性的值

话虽如此,POST方法中的代码毫无意义。您所要做的就是创建
网页的新实例并保存它。如果要将天数添加到选定的
网页
,则需要从数据库中再次获取、更新并保存。代码应该是

[HttpPost]
public async Task<ActionResult> Renewal(RenewalViewModel vm)
{
    if (!ModelSTate.IsValid)
    {
        // Populate the SelectList's
        model.Webpage = ....
        model.AddTime = ....
        return View(vm);
    }
    // Get the data model
    WebPages model = db.WebPagesList.Where(x => x.WebPagesId == vm.SelectedWebPage).FirstOrDefault();
    if (model != null)
    {
        // Not really sure if you mean AddYears or AddDays?
        model.DomainExp = model.DomainExp.AddYears(vm.SelectedDurationDays);
        db.Entry(model).State = EntityState.Modified;
        db.SaveChanges();
    }
    // Redirect
    return RedirectToAction(....);
}
然后在返回视图之前在两个方法中调用它

ConfigureRenewalViewModel(vm);
return View(vm);

视图中的模型是
@model RenewalViewModel
,因此您需要返回
RenewalViewModel
,而不是
网页
模型-即
返回视图(vm)
但是在这种情况下,如果
DomainExp
进入
WebPages
model对不起,我不理解你的评论-在你的
更新
方法或相关视图模型中没有任何地方引用任何现有的
网页
-你所做的就是创建和保存一个新的
网页
。然后你需要从数据库中获取现有的
网页
,并更新其
域我看到你接受了,然后又不接受。有什么你不理解的吗?太好了,你能推荐我读一些东西来创建单独的方法吗?我假设我在控制器和模型中使用
private void…
。网页
等于网页模型的
DomainName
private void配置RenewalViewModel(RenewalViewModel模型)
进入控制器,这意味着不必在GET和POST(如果需要返回视图)中复制创建选择列表的代码,而只需在一个位置(即DRY principal)。但是我不明白你所说的
模型是什么意思。网页
等于网页模型的
域名
,我明白了!,有一个问题,“使用单独的方法”仅适用于最佳实践,或者它会影响加载速度或类似情况?对性能没有影响-它的最佳实践是因为您没有复制代码(如果您以后必须修改它,那么您只需要在一个位置修改它)
return View(vm);
[HttpPost]
public async Task<ActionResult> Renewal(RenewalViewModel vm)
{
    if (!ModelSTate.IsValid)
    {
        // Populate the SelectList's
        model.Webpage = ....
        model.AddTime = ....
        return View(vm);
    }
    // Get the data model
    WebPages model = db.WebPagesList.Where(x => x.WebPagesId == vm.SelectedWebPage).FirstOrDefault();
    if (model != null)
    {
        // Not really sure if you mean AddYears or AddDays?
        model.DomainExp = model.DomainExp.AddYears(vm.SelectedDurationDays);
        db.Entry(model).State = EntityState.Modified;
        db.SaveChanges();
    }
    // Redirect
    return RedirectToAction(....);
}
private void ConfigureRenewalViewModel(RenewalViewModel model)
{
    model.Webpage = ....
    model.AddTime = ....
}
ConfigureRenewalViewModel(vm);
return View(vm);