gpt4 book ai didi

c# - MVC结构查询

转载 作者:行者123 更新时间:2023-11-30 17:42:27 25 4
gpt4 key购买 nike

总而言之,我正在努力寻找正确的简单 ASP.NET MVC 结构。从一开始我就应该说我对 ASP 和 MVC 完全陌生,我以前用过一点 C#。

举个例子,假设我正在尝试检查两条信息,例如用户根据存储所有用户信息的数据库输入的用户名和密码。如果他们输入了正确的凭据,则会显示用户信息摘要,否则他们将被收回(视觉上永远不会离开)登录页面,并显示请重试消息。

所以我有我的主页(登录页面) View 、一个HomeController 和一个HomeIndexViewModel。同样,我有一个帐户 View 、一个 AccountController 和一个 AccountUserViewModel(还有一个 AccountIndexViewModel,但并未真正使用)。

主页 View “接受”(通过它的 Controller )一个 HomeIndexVM 作为它的模型:

@model ViewModels.HomeIndexViewModel

@using (Html.BeginForm("User", "Account", FormMethod.Post))
{
if (@Model.PreviousAttempts)
{
<p><b>Username or password were not recognised please try again.</b></p>
}

<p>Username: @Html.TextBoxFor(x => x.Username)</p>
<p>Password: @Html.PasswordFor(x => x.Password)</p>
<input id="btnLogin" type="submit" value="Login" />
}

家庭 Controller :

public class HomeController : Controller
{
public ActionResult Index(bool invalidLogin = false)
{
var vm = new HomeIndexViewModel() { Username = string.Empty, Password = string.Empty, PreviousAttempt = invalidLogin };

return View(vm);
}
}

最后是 HomeIndexViewModel.cs

public class HomeIndexViewModel
{
public string Username { get; set; }
public string Password { get; set; }
public bool PreviousAttempt { get; set; }
}

到目前为止,我认为还可以。现在单击登录按钮,它将发布到帐户、用户。

public ActionResult User(UserLogin userLogin)
{
if (!ModelState.IsValid)
return RedirectToAction("Index", "Home", new { invalidLogin = true });

// Match username and password against database
User user = userLogin.IsValid(userLogin.Username, userLogin.Password);
if (user != null)
{
return this.View(user);
}

return RedirectToAction("Index", "Home", new { invalidLogin = true });
}

这里有几件事,您可以看到重定向回登录页面,并带有 true 标志以显示失败的登录消息。

但更重要的是,我认为它无法正常工作,因为它需要 UserLogin 作为参数。这是一个模型对象,包含:

public class UserLogin
{
private NewDBSolution_v1Entities accountsDB = new NewDBSolution_v1Entities();

[Required, MinLength(2)]
public string Username { get; set; }

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

public bool PreviousAttempts { get; set; }

public User IsValid(string username, string password) // Ideally use the local username and password properties rather than pass in as they are the same.
{
// Match username and password against database and return full user info if match found, otherwise return null
}
}

那么我要问的是……在这种情况下,最好的做法是帐户的用户操作采用 HomeIndexViewModel,即使它是主页而不是帐户相关?或者我应该像最初那样传入一个模型对象,并将其用于验证(我不喜欢的是验证是在从不同 View 传递的对象中完成的,如果这有意义的话?)

如何最好地将 View 中的信息捆绑起来传递给操作?我意识到编译器并不关心 VM 和模型对象,它们只是类,但我想让我的关注点分离正确。

基本上我需要的只是主页 View 中的用户名和密码,应该将其绑定(bind)到 VM 还是 M?

在我看来,有可能会出现很多只是略有不同的类,所以为什么不制作一个并使用它呢。我想这就是继承的用武之地,但如果子类只添加一个不同的属性,你会从中受益吗?

无论如何,我一直在寻找最佳的结构方式。我确实在某处读到过,VM 基本上应该是模型的掩码/适配器,这样 View 只能看到它需要的东西。但是这些 VM 没有与之关联的模型。

我现在正在胡说八道,如果有人能弄清这一点并给我一些指示,我将不胜感激,谢谢。

最佳答案

我认为您可能在原地打转,因为您已经在 HomeController 中创建了登录 View 。登录代码与帐户相关,那么为什么不将其放入 AccountController 中呢?

如果您遵循 Post-Redirect-Get 模式,就像您在此处尝试做的那样,我倾向于赞成发布到与您从中获得的相同操作。我会将登录操作移动到 AccountController 中。我会将执行数据库检查的代码移到一个单独的类中,而不是将其保留在模型中。也许是成员(member)提供者或类似的东西。我会将那个提供者传递给 Controller ​​——这允许 Controller 和模型对象不再担心如何决定用户是否有效。他们可以要求提供者告诉他们。

保持实体(无论是 UI 还是域)简单通常是一种很好的做法。他们当然应该在其中包含数据库连接对象。

你的 Controller 看起来像这样:

public class AccountController : Controller
{
private readonly IMembershipProvider membershipProvider;

public AccountController(IMembershipProvider membershipProvider)
{
this.membershipProvider= membershipProvider;
}

public ActionResult Login()
{
var viewModel = new LoginViewModel();
return View(viewModel);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View(viewModel);
}

var user = membershipProvider.Find(viewModel.Username, viewModel.Password);
if (user != null)
{
membershipProvider.SignIn(user, true);
return RedirectToAction("Index", "Home");
}

ModelState.AddModelError("Login", "Your credentials were not recognised. Please try again.");
return View(viewModel);
}
}

因为登录操作对于 Get 和 Post 具有相同的名称,所以您的 View 变得更简单。您将在 Views/Account 文件夹中有一个 Login.cshtml View ,如下所示:

@model ViewModels.LoginViewModel

@using (Html.BeginForm())
{
@Html.AntiForgeryToken() // good practice to add this, ties in with the ValidateAntiForgeryToken attribute on the Post action
@Html.ValidationSummary() // displays model errors if there are any

<p>Username: @Html.TextBoxFor(x => x.Username)</p>
<p>Password: @Html.PasswordFor(x => x.Password)</p>
<input id="btnLogin" type="submit" value="Login" />
}

要回答这个具体问题:

How do you best bundle information up from a view to pass to an Action?

如果可以的话,让默认的模型绑定(bind)器来处理。它非常强大,可以处理大多数有关从表单传回数据的情况。模型绑定(bind)器所做的只是匹配表单集合中的名称-值对,当表单被发布到您的类的属性时,表单集合被传回。如果您的类具有字符串属性 UsernamePassword,模型绑定(bind)器将填充它们。就模型绑定(bind)器而言,您提供的实际类是无关紧要的。这同样有效(但从事该项目的任何其他人都不会感谢您!):

public class Dave
{
[Required, MinLength(2)]
public string Username { get; set; }

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

然后在 Post Action 中:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(Dave dave)
{
...
}

这有帮助吗?

关于c# - MVC结构查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31994930/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com