这是我的模特:
public sealed class UserModel
{
[Key]
[Required]
[StringLength(20, MinimumLength = 4)]
public string Username { get; set; }
[Required]
[EmailAddress]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[StringLength(20, MinimumLength = 4)]
public string Password { get; set; }
public bool IsValid { get; set; }
}
Username
,Email
和Password
由用户提供,但IsValid
只应由服务器修改,换句话说,如果用户提供{{} 1}}服务器应返回true
或不考虑此值。
因此,我可以在创建模型时将属性设置为BAD REQUEST
,但它不干净。
有没有办法将属性设为私有或“仅服务器”?
[2018年4月1日]:
我发现nice article使用了false
,遗憾的是它不能用于[BindNever]
指向here的数据。所以目前我只是自己在POST处理程序中将属性设置为[FromBody]
,但它非常难看,因此我仍然在寻找其他方法来做到这一点!
[2018年4月2日]: 终于找到了 ! Check this out !
答案 0 :(得分:1)
创建一个用户将直接在视图中与之交互的视图模型。尽量不要在视图中直接使用模型,因为这基本上是一个漏洞设计。
public class UserViewModel {
[Required]
[StringLength(20, MinimumLength = 4)]
public string Username { get; set; }
[Required]
[EmailAddress]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
[StringLength(20, MinimumLength = 4)]
public string Password { get; set; }
}
在服务器端,属性将在持久化数据时复制到模型。需要设置的任何其他属性都可以在服务器上安全地完成,因为模型没有泄露给客户端。
例如
public ActionResult Post([FromBody] UserViewModel viewModel) {
if(ModelState.IsValid) {
//create new model
var model = new UserModel {
Username = viewModel.Username,
Email = viewModel.Email,
Password = viewModel.Password
};
//or model retrieved from data storage
//...some other code...
model.IsValid = true; //only the server can modify this value
//...
}
//...
}
如果不想与IsValid
属性进行交互,客户端甚至不应该知道require 'rails/all'
RSpec.describe WikisController, type: :controller do
let(:user) { User.create!(email: "user@email.com", password: "password") }
let(:wiki) { Wiki.create!(title: "New Wiki Title", body: "New Wiki Body", private: false, user: user) }
describe "GET show" do
it "returns http success" do
get :show
expect(response).to have_http_status(:success)
end
end
describe "GET edit" do
it "returns http success" do
get :edit
expect(response).to have_http_status(:success)
end
end
end
属性。
答案 1 :(得分:0)
以下是如何实现它:
请求处理程序(在您的控制器中):
[HttpPost]
public async Task<IActionResult> PostUserModel([FromBody] UserModel userModel)
{
if (!ModelState.IsValid) return BadRequest(ModelState);
_context.Users.Add(userModel);
await _context.SaveChangesAsync();
return CreatedAtAction(nameof(GetUserModel), new {id = userModel.Username}, userModel);
}
模型(在我们的例子中是UserModel):
[DataContract]
public sealed class UserModel
{
[Key]
[DataMember(IsRequired = true)]
[StringLength(20, MinimumLength = 4)]
public string Username { get; set; }
[EmailAddress]
[DataMember(IsRequired = true)]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[DataType(DataType.Password)]
[DataMember(IsRequired = true)]
[StringLength(20, MinimumLength = 4)]
public string Password { get; set; }
public bool IsValid { get; set; }
}
我们将模型定义为数据契约,因此,只有[DataMember]
s将被绑定和序列化!
这是非常干净的&amp;很好,因为非[DataMember]
属性存储在数据库中,它们不是私有的或类似的东西,它们不受序列化的影响,这意味着如果你将模型发送到客户端,例如,他&# 39; ll看不到非[DataMember]
字段。
你也可以这样做:
public sealed class UserModel
{
[Key]
[Required]
[StringLength(20, MinimumLength = 4)]
public string Username { get; set; }
[EmailAddress]
[Required]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[DataType(DataType.Password)]
[Required]
[StringLength(20, MinimumLength = 4)]
public string Password { get; set; }
[JsonIgnore]
public bool IsValid { get; set; }
}
当然,它仍然比在创建时将属性设置为false
更好,但我发现第一种方法更好,因为您不需要Json.Net
并且它可以防止您忘记保护&#34;私人&#34;属性。
无论如何希望这会帮助你们!
如果您使用除JSON [NeverBind]
之外的其他来源创建模型,则可能还需要添加[FromBody]
属性