c# - ASP.NET Core 自定义验证创建模型的新实例

标签 c# asp.net asp.net-mvc asp.net-core model-validation

我正在玩 ASP.NET Core 并尝试为简单的文字游戏设计一个 UI。您会收到一个随机生成的长词,您需要根据长词提供的字母提交较短的词。

该应用程序还没有使用任何类型的存储库,它现在只是将模型实例作为静态字段存储在 Controller 中。

我目前面临一个问题,每次验证新提交的单词时,都会创建一个新的游戏实例,这自然会保证呈现验证错误,因为每个游戏都提供了一个新的长单词。

我一定是误解了模型验证的工作方式,但调试并没有给我任何比每次都显示一个新的长单词的验证上下文更好的线索。

我卡住了,请帮忙。

这是 Controller :

public class HomeController : Controller
{
    private static WordGameModel _model;

    public IActionResult Index()
    {
        if (_model == null)
        {
            _model = new WordGameModel();
        }
        return View(_model);
    }

    [HttpPost]
    public IActionResult Index(WordGameModel incomingModel)
    {
        if (ModelState.IsValid)
        {
            _model.Words.Add(incomingModel.ContainedWordCandidate);
            return RedirectToAction(nameof(Index), _model);
        }
        return View(_model);
    }
}

游戏模型:

public class WordGameModel
{
    public WordGameModel()
    {
        if (DictionaryModel.Dictionary == null) DictionaryModel.LoadDictionary();
        LongWord = DictionaryModel.GetRandomLongWord();
        Words = new List<string>();
    }

    public string LongWord { get; set; }
    public List<string> Words { get; set; }

    [Required(ErrorMessage = "Empty word is not allowed")]
    [MinLength(5, ErrorMessage = "A word shouldn't be shorter than 5 characters")]
    [MatchesLettersInLongWord]
    [NotSubmittedPreviously]
    public string ContainedWordCandidate { get; set; }

    public bool WordWasNotSubmittedPreviously() => !Words.Contains(ContainedWordCandidate);
    public bool WordMatchesLettersInLongWord()
    {
        if (string.IsNullOrWhiteSpace(ContainedWordCandidate)) return false;
        return ContainedWordCandidate.All(letter => LongWord.Contains(letter));
    }
}

验证失败的自定义验证属性:

internal class MatchesLettersInLongWord : ValidationAttribute
{
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        WordGameModel model = (WordGameModel) validationContext.ObjectInstance;

        if (model.WordMatchesLettersInLongWord()) return ValidationResult.Success;

        return new ValidationResult("The submitted word contains characters that the long word doesn't contain");
    }
}

查看:

@model WordGameModel

<div class="row">
    <div class="col-md-12">
        <h2>@Model.LongWord</h2>
    </div>
</div>

<div class="row">
    <div class="col-md-6">
        <form id="wordForm" method="post">
            <div>
                <input id="wordInput" asp-for="ContainedWordCandidate"/>
                <input type="submit" name="Add" value="Add"/>
                <span asp-validation-for="ContainedWordCandidate"></span>
            </div>

        </form>
    </div>
</div>

<div class="row">
    <div class="col-md-6">
        <ul>
            @foreach (var word in @Model.Words)
            {
                <li>@word</li>
            }
        </ul>
    </div>
</div>

谢谢。

最佳答案

您的 View 需要为 LongWord 包含一个隐藏输入,以便在 POST 方法中,以便在 ModelBinder 调用您的构造函数后,设置 LongWord基于表单值(即您发送到 View 的值)

<form id="wordForm" method="post">
    <div>
        <input type="hidden" asp-for="LongWord" /> // add hidden input
        <input id="wordInput" asp-for="ContainedWordCandidate"/>
        <input type="submit" name="Add" value="Add"/>
        <span asp-validation-for="ContainedWordCandidate"></span>
    </div>
</form>

作为旁注,在您的 post 方法中,它应该只是 return RedirectToAction(nameof(Index)); - GET 方法没有(也不应该)有模型参数,所以传递它是没有意义的(而且它只会创建一个丑陋的查询字符串)

关于c# - ASP.NET Core 自定义验证创建模型的新实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52994266/

相关文章:

c# - 双击时停止单元格进入编辑模式

C# UTC 到用户本地时间

asp.net mvc3 如果编辑上没有上传图像,图像编辑将被覆盖

asp.net-mvc - MVC 中用于灵活调查的正确模型

c# - .Net Core 3 worker 服务应用程序,带有带参数的构造函数的插件

c# - 如何在C#中使用DataAdapter和存储过程对数据访问进行事务控制?

c# - 全局异常处理程序是否意味着删除不必要的 try catch block ?

c# - 使用 Entity Framework V1 更新外键(实体)

c# - 在我的部分观点中语言没有改变?

c# - 为具有抽象复杂类型的模式生成类