【问题标题】:NET CORE 3.1 MVC HttpPost Controller action gets a NULL parameter on form submit in viewNET CORE 3.1 MVC HttpPost 控制器操作在视图中提交表单时获取 NULL 参数
【发布时间】:2020-11-19 14:27:40
【问题描述】:

我在 MVC 视图中提交注册表单,但在控制器中调试 RegisterViewModel 参数时始终为 NULL。

请教几个问题:

  1. 为什么控制器中 RegisterViewModel 参数的字段为 NULL?
  2. 是否可以在同一个项目中使用 RAZOR PAGES 和 MVC VIEWS,混合使用 他们?
  3. 为什么标签助手(例如“asp-for”)没有被 Intellisense 着色为绿色(在 Register.chtml 中是蓝色的)?

观点:

@model MyProjectNamespace.Data.ViewModels.RegisterModel

@{
    Layout = "_Layout";
    ViewBag.Title = "User Registration";
}

<h1>User Registration</h1>


<div class="row">
    <div class="col-sm-4">

    </div>

    <div class="col-sm-4">
        <form method="post">
            <div asp-validation-summary="All" class="text-danger">
                <div class="form-group">
                    <label class="control-label">Email</label>
                    <input asp-for="Email" class="form-control" type="text" />
                </div>
                <div class="form-group">
                    <label class="control-label">Password</label>
                    <input asp-for="Password" class="form-control" type="password" />
                    <span asp-validation-for="Password" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label class="control-label">Confirm Password</label>
                    <input asp-for="ConfirmPassword" class="form-control" type="password" />
                    <span asp-validation-for="ConfirmPassword" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label class="control-label">Company</label>
                    <input asp-for="CompanyID" class="form-control" type="text"/>
                </div>

                <button type="submit" class="btn btn-primary">Register</button>
            </div>
        </form>
    </div>
</div>

控制器:

namespace MyProjectNamespace.Controllers
{
    //[AllowAnonymous]
    public class AccountController : Controller
    {
        private readonly UserManager<ApplicationUser> userManager;
        private readonly SignInManager<ApplicationUser> signInManager;

        public AccountController(UserManager<ApplicationUser> userManager,
                                 SignInManager<ApplicationUser> signInManager  )
        {
            this.userManager = userManager;
            this.signInManager = signInManager;
        }

        // only one page load, NOT submit
        //[HttpGet]
        public IActionResult Register()
        {
            return View();
        }


        //answers on submit
        [HttpPost]
        public async Task<IActionResult> Register(RegisterViewModel registerViewModel)
        {
            if (ModelState.IsValid)
            {
                //create new user
                var user = new ApplicationUser
                {
                    UserName = registerViewModel.Email,
                    Email = registerViewModel.Email
                };

                var result = await userManager.CreateAsync(user, registerViewModel.Password);

                if (result.Succeeded)
                {
                    await signInManager.SignInAsync(user, isPersistent: false); // create cookie that only lasts for the session
                    return RedirectToAction("index", "home");
                }

                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError("", error.Description); // these errors are added in the view by asp-validation-summary="All"
                }
            }
            else
            {
                // re-render the register view and display errors
            }

            return View(registerViewModel);
        }
    }
}

Startup.cs

namespace MyProject
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));

            //services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
            //    .AddEntityFrameworkStores<ApplicationDbContext>();

            //services.AddIdentity<ApplicationUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)
            //    .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddRazorPages().AddRazorRuntimeCompilation();

            // added for mvc
            services.AddControllersWithViews();

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                // added for razor pages routing
                endpoints.MapRazorPages();

                // added for mvc routing 
                endpoints.MapControllerRoute(
                     name: "default",
                     pattern: "{controller}/{action}/{id?}");
            });
        }
    }
}

模型类:

namespace MyProjectNamespace.Data.ViewModels
{
    public class RegisterModel
    {
        [Required]
        [EmailAddress]
        public string Email { get; set; }

        [Required]
        [DataType(DataType.Password)]
        public string Password { get; set; }

        [DataType(DataType.Password)]
        [Display(Name ="Confirm password")]
        [Compare("Password", ErrorMessage = "Passwords do not match.")]
        public string  ConfirmPassword { get; set; }

        public string CompanyID { get; set; }
    }
}

【问题讨论】:

  • 你能显示RegisterViewModel类吗?
  • @ShadiNamrouti 我添加了模型类。
  • 您正在使用RegisterViewModel,但我们只能在您的项目中看到RegisterModel
  • 不要在&lt;div asp-validation-summary="All" class="text-danger"&gt;里面放任何内容
  • 感谢您的建议,它应该是RegisterViewModel,但我后来更改了模型类的名称。我让它工作但创建了另一个项目,不确定这个项目有什么问题。我创建了另一个 net core 3.1 mvc 但没有 razor pages 项目并且相同的代码工作。

标签: asp.net-core .net-core razor-pages


【解决方案1】:
  1. 为什么控制器中 RegisterViewModel 参数的字段为 NULL?

这很奇怪,它适用于我的代码和你一样。请确保view 中的Modelcontroller 中的型号相同。

  1. 可以在同一个项目中混合使用 RAZOR PAGES 和 MVC VIEWS 吗?

您可以在同一个项目中使用MVCrazor page。您已经在项目中注册了剃刀页面服务。只需在项目root目录下创建Pages文件夹,然后在该文件夹下新建一个Razor页面文件,右键该文件夹:Add -> Razor Page

我之前在这个answer测试过。

  1. 为什么标签助手(例如“asp-for”)没有被 Intellisense 着色为绿色(在 Register.chtml 中是蓝色的)?

这取决于你的 VS 的版本。

对于 VS 2015,这里是来自 @Murat SEKER 的 answer

  1. 从包管理器控制台安装Razor tool

    安装包Microsoft.AspNetCore.Razor.Tools

  2. 从市场下载并安装Razor Language Services。 (您的 Visual Studio 实例应该关闭)

重新启动 Visual Studio 后,intellisense 和着色应该对标签助手起作用。

【讨论】:

    猜你喜欢
    • 2020-10-12
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    • 2020-09-27
    • 2019-10-28
    • 1970-01-01
    相关资源
    最近更新 更多