【问题标题】:Passing data from view to controller and from controller back to view将数据从视图传递到控制器并从控制器传回视图
【发布时间】:2021-11-14 02:35:47
【问题描述】:

我在 ASP.NET 中编写一个简单的应用程序时遇到问题。 我的想法是从该表单传递数据以在我的控制器中创建电影,然后我希望此控制器(AddMovie)将此电影发送到我的电影列表,并且我希望它显示在视图中。 我尝试了一些方法,但都没有奏效。我该怎么做?

查看:

@model IEnumerable<Movie>
@{
    // ViewData["Title"] = "MovieView";

    ViewBag.Title = "Welcome to My Page";

}
<h1>MoviesView</h1>

@foreach (var item in Model)
{
<div class="text-center">
    <p>Id:item.Id </p>
    <p>Name:item.Name</p>
    <p>Author: item.Author</p>
   
</div>
<br />
}
<br />
<form asp-controller="MoviesController" method="post">
    Id: <input type="text" name="movieId" /><br />
    Name: <input type="text" name="movieName" /><br />
    Author: <input type="text" name="movieAuthor" />
    <input type="submit" value="Submit" formaction="AddMovie" /> &nbsp;&nbsp;&nbsp;

</form>
<p>@ViewBag.Result</p>

控制器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using WebMVCAPP_L.Models;

namespace WebMVCAPP_L.Controllers
{
    public class MoviesController : Controller
    {
        List<Movie> movieList = new List<Movie>();

        public IActionResult Index()
        {
            return View(movieList);
        }
        [HttpPost]
        public IActionResult AddMovie()
        {
            int id = Convert.ToInt32(HttpContext.Request.Form["movieId"].ToString());
            string name = HttpContext.Request.Form["movieName"].ToString();
            string author = HttpContext.Request.Form["movieAuthor"].ToString();

            Movie movie = new Movie(id,name,author);
            movieList.Add(movie);
            return View("Index");
        }
    }
}

【问题讨论】:

  • 我建议您不要提供这么大的代码块,而只提供不起作用的行。

标签: c# asp.net-core asp.net-core-mvc


【解决方案1】:

首先,您需要某种方式来持久化您的List&lt;Movie&gt;()。 HTTP,因此 MVC,是无状态的。理想情况下,您将使用数据库,但您可以使用 Session 进行测试:

List<Movie> movieList
{
    get
    {
        if (Session["movieList"] == null)
        {
            Session["movieList"] = new List<Movie>();
        }
        return Session["movieList"] as List<Movie>;
    }
}

您还需要将asp-action 添加到您的表单中,以回复您的AddMovie 方法:

<form asp-controller="MoviesController" asp-action="AddMovie" method="post">

然后,更改您的方法签名:

public IActionResult AddMovie(int id, string name, string author)

MVC 框架会自动将表单字段绑定到同名的参数。

最后,返回一个 HTTP 重定向而不是视图本身:

[HttpPost]
public IActionResult AddMovie()
{
    Movie movie = new Movie(id, name, author);
    movieList.Add(movie);
    return RedirectToAction("Index");
}

然后,浏览器将对(持久的)电影列表的Index 方法执行 HTTP GET。

【讨论】:

    【解决方案2】:

    它向我展示了类似An unhandled exception occurred while processing the request. InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure.DefaultTempDataSerializer' cannot serialize an object of type 'System.Collections.Generic.List`1[WebMVCAPP_L.Models.Movie]'. Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure.DefaultTempDataSerializer.Serialize(IDictionary<string, object> values)

    Stack Query Cookies Headers Routing 
    
    InvalidOperationException: The 'Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure.DefaultTempDataSerializer' cannot serialize an object of type 'System.Collections.Generic.List`1[WebMVCAPP_L.Models.Movie]'.
        Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure.DefaultTempDataSerializer.Serialize(IDictionary<string, object> values)
        Microsoft.AspNetCore.Mvc.ViewFeatures.CookieTempDataProvider.SaveTempData(HttpContext context, IDictionary<string, object> values)
        Microsoft.AspNetCore.Mvc.ViewFeatures.TempDataDictionary.Save()
        Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.SaveTempDataFilter.SaveTempData(IActionResult result, ITempDataDictionaryFactory factory, IList<IFilterMetadata> filters, HttpContext httpContext)
        Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.SaveTempDataFilter.OnResultExecuted(ResultExecutedContext context)
        Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext<TFilter, TFilterAsync>(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
        Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
        Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)
        Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
        Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
        Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
        Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
        Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
        Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
        Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)```
    

    【讨论】:

      【解决方案3】:

      当您从一个操作路由到另一个操作时,您需要使用临时数据。

      namespace WebMVCAPP_L.Controllers
      {
          public class MoviesController : Controller
          {
              List<Movie> movieList = new List<Movie>();
      
              public IActionResult Index()
              {
                  if(TempData["myData"]!=null){
      
                      movieList = JsonConvert.DeserializeObject<List<Movie>>((String)TempData["myData"]);
                   }
                  return View(movieList);
              }
              [HttpPost]
              public IActionResult AddMovie()
              {
                  int id = Convert.ToInt32(HttpContext.Request.Form["movieId"].ToString());
                  string name = HttpContext.Request.Form["movieName"].ToString();
                  string author = HttpContext.Request.Form["movieAuthor"].ToString();
      
                  Movie movie = new Movie(id,name,author);
                  movieList.Add(movie);
                   String str = JsonConvert.SerializeObject(movieList)
                   TempData["myData"] = str ;
                  return View("Index");
              }
          }
      }
      
      <form asp-action="AddMovie" asp-controller="Movies">
      
          <input type="submit" />
      </form>
      

      【讨论】:

      • 我已经更新了我的答案。您需要在表单中传递上述值。
      • 我认为电影列表需要比单个 HTTP 请求保留更长的时间。
      • 我有更改代码,Asp.Net Core MVC 目前不支持 TempData 的复杂数据类型。它现在只支持字符串。它在序列化数据时通过这个异常,如果我们传递其他字符串。我将我的列表序列化为 json,然后保存在 TempData 中。这是我如何做到的。我创建扩展方法来从 TempData 添加和检索数据。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多