简体   繁体   English

OnPost之后如何在我的视图中保留模型?

[英]How can I keep my model in my View after OnPost?

I'm on a project with .Net Core and I'm using ASP Razor Pages. 我正在使用.Net Core进行项目,并且正在使用ASP Razor Pages。 In my model, I have an OnGet which load all the data I need in my view. 在我的模型中,我有一个OnGet,可以加载视图中所需的所有数据。

public IList<Projet> Projets { get; set; }
public ActionResult OnGet()
{
    Projets = _serviceSelect.getProjets();
    return Page();
}

Then, in my OnPost which is activated when I submit my form. 然后,在我提交表单时激活的OnPost中。

<form method="post">
    <div asp-validation-summary="All" class="text-danger"></div>
    <input type="radio" value="1" asp-for="LoginData.TypeCompte" />choice<br />
    Username: <input asp-for="LoginData.Username" /><br />
    Password: <input asp-for="LoginData.Password" /><br />
    Remember me: <input asp-for="LoginData.RememberMe" type="checkbox" /><br />
    <input asp-page-handler="connexion" type="submit" value="Login" />
    @Html.AntiForgeryToken()
</form>

I would like to display an error in my view, using my ModelState. 我想使用我的ModelState在我的视图中显示错误。

public ActionResult OnPostConnexion()
{
    if (ModelState.IsValid)
    {
       // Do stuff 
    }
    else
    {
        ModelState.AddModelError("", "username or password is blank");
        return Page();
    }
}

But, when I return Page(), It's like the model is reload and when I try to access to my data, my objects are null. 但是,当我返回Page()时,就像重新加载模型一样,当我尝试访问数据时,我的对象为null。

 Object reference not set to an instance of an object.
@foreach (var item in Model.Projets)

How can I update my view without losing my data contain in the model ? 如何在不丢失模型中包含的数据的情况下更新视图?

The reason you are getting an object reference error is because the Model.Projects has not been populated when returning the view and therefore cannot iterate in the foreach loop. 返回对象引用错误的原因是,返回视图时未填充Model.Projects,因此无法在foreach循环中进行迭代。

Based off your existing code, you could populate your model again before returning the page. 根据现有代码,您可以在返回页面之前再次填充模型。

public ActionResult OnPostConnexion()
{
    if (ModelState.IsValid)
    {
       // Do stuff 
    }
    else
    {
        Projets = _serviceSelect.getProjets();

        ModelState.AddModelError("", "username or password is blank");
        return Page();
    }
}

A better solution would be: 更好的解决方案是:

public ActionResult OnPostConnexion(viewModel model)
{
    if (!ModelState.IsValid)
    {
       return View(model);
    }
    else
    {
        //do stuff
    }
}

When you call "Page()" this is asking for a new Page object, when you return that object it will be blank. 当您调用“ Page()”时,它将要求一个新的Page对象,当您返回该对象时,它将为空。 Pages and views are different, generally with ASP you will use views, there are some good articles on MSDN about the differences and why but for now just if you change Page() to View() it should resolve the issue. 页面和视图是不同的,通常使用ASP时会使用视图,MSDN上有一些很好的文章介绍了它们之间的差异以及原因,但是就目前而言,即使将Page()更改为View(),它也可以解决问题。

You need to fix two things in your code: 您需要在代码中修复两件事:

First you need to mark your Projets property with [BindProperty], like this: 首先,您需要使用[BindProperty]标记Projets属性,如下所示:

[BindProperty]
public IList<Projet> Projets { get; set; }

Then you need to recode your Page so that the fields of Projets are inside of the form tag so they get posted back to the page and then you need to rewrite how you output them: 然后,您需要重新编码Page,以使Projets的字段位于form标记内,以便将它们重新发布到页面上,然后您需要重写输出方式:

<form method="post">
    <div asp-validation-summary="All" class="text-danger"></div>
    <input type="radio" value="1" asp-for="LoginData.TypeCompte" />choice<br />
        Username: <input asp-for="LoginData.Username" /><br />
        Password: <input asp-for="LoginData.Password" /><br />
        Remember me: <input asp-for="LoginData.RememberMe" type="checkbox" /><br />
    <input asp-page-handler="connexion" type="submit" value="Login" />
    @Html.AntiForgeryToken()

    <!-- SEE REMARK BELOW! -->
    @{
        for (int i = 0; i < Model.Projets.Count; i++)
        {
            <input asp-for="@Model.Projets[i].FieldOne" />
            <br />
            <input asp-for="@Model.Projets[i].FieldTwo" />
        }
    }

</form>

REMARK You need to render your fields in a list in such way that they get unique ID's so that the ModelBinder can retrieve them on Post. 备注您需要以列表的形式呈现字段,使它们获得唯一的ID,以便ModelBinder可以在Post上检索它们。 In my case I named one field FieldOne and this is how it is rendered: 在我的情况下,我命名了一个字段FieldOne,这就是它的呈现方式:

<input type="text" id="Projets_0__FieldTwo" name="Projets[0].FieldTwo" value="one">

I faced the same issue and noone from suggested solution worked. 我遇到了同样的问题,建议的解决方案中没有人起作用。 I resolved it with simple usage of helping class that keeps the model for me. 我通过简单地使用帮助类来解决该问题,该类可以为我保留模型。 The solution is not elegant but effective :) 该解决方案不是很好,但有效:)

public interface ISessionHelper
    {
        void AddRenewItem(string key, object item);
        object GetItem(string key);
    }
public class SessionHelper : ISessionHelper
{
    private readonly Dictionary<string, object> _sessionBag;

    public SessionHelper()
    {
        _sessionBag = new Dictionary<string, object>();
    }

    public void AddRenewItem(string key, object item)
    {
        if (_sessionBag.Keys.Contains(key)) _sessionBag.Remove(key);
        _sessionBag.Add(key, item);
    }

    public object GetItem(string key)
    {
        if (_sessionBag.Keys.Contains(key))
        {
            return _sessionBag[key];
        }
        return null;
    }
}

In my get method I add an item to the dictionary: 在我的get方法中,我向字典添加了一个项目:

 public async Task<IActionResult> OnGetAsync(int? id)
    {
      ...
        _sessionHelper.AddRenewItem(this.ToString(), this);
        ...

    }

In my post method I take the model back from the dictionary and assign required properties for the current model: 在我的post方法中,我从字典中取出模型并为当前模型分配所需的属性:

 public async Task<IActionResult> OnPostApplyGuess(int itemId)
    {
        GameModel model = (GameModel) _sessionHelper.GetItem(this.ToString());
        MyProp1= model.MyProp1;
        MyProp2 = model.MyProp2 ;
        MyProp3= model.MyProp3;

        if (!ModelState.IsValid)
        {
            return Page();
        }

        return Page();
    }

Do not forget to add the service as a Singleton: 不要忘记将服务添加为Singleton:

services.AddSingleton<ISessionHelper, SessionHelper>();

I hope it helped to somebody :) 我希望它对某人有所帮助:)

I solved this issue by replacing return Page(); 我通过替换return Page();解决了这个问题return Page(); with return this.OnGet(); return this.OnGet(); in public ActionResult OnPostConnexion() public ActionResult OnPostConnexion()

That way any logic you have in the OnGet which populates PageModel properties gets reused. 这样,您在OnGet中填充PageModel属性的任何逻辑都将被重用。

So my full example looks like: 所以我的完整示例如下所示:

    public IEnumerable<SelectListItem> CompanyListing { get; private set; }

    public async Task<IActionResult> OnGet()
    {
        if (!string.IsNullOrEmpty(this.ErrorMessage))
        {
            this.ModelState.AddModelError(string.Empty, this.ErrorMessage);
        }

        this.CompanyListing = await this.PopulateCompanyList();
        return this.Page();
    }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!this.ModelState.IsValid)
        {
            // Something failed. Redisplay the form.
            return await this.OnGet();
        }

        return this.RedirectToPage("/");
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在我的视图中访问模型中的属性 - How can I access the attributes from my model in my view 如何从视图中获得双倍到我的 Model? - How can I get a double from the View into My Model? 在我看来,如何处理代表 model? - How can I handle delegates in my view model? 如何将我的自定义用户控件及其自定义视图 model 包含到我的 xaml 视图中? - How can I include my custom user control with its custom view model into my xaml view? 如何在我的视图(IEnumerable)中对列表进行排序并保持过滤到位? - How can I sort the list in my view (IEnumerable) and keep my filtering in place? 在执行“从数据库更新 Model”时,如何防止我的 model 文件被刷新? - How can I keep my model files from being refreshed when doing an "Update Model from Database"? 我怎样才能制作我的视图模型 - How could I make my View Model 如何使用foreach将模型中的属性输入到视图中? - How can I get my properties from a Model into my View with a foreach? 如果模型的给定属性没有值,如何在视图中不呈现按钮? - How can I not render a button in my view if a given property off my model has no value? 如何在我的视图中仅显示不同的名称(来自模型)? - How can I show just distinct names (from my model) in my view?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM