簡體   English   中英

無法將字節設為必填字段

[英]Cannot make Byte a Required Field

有一個我想上傳圖像的應用程序。 我為此使用字節數組。

該圖像是必需的,但是當我將該注釋放在變量上並嘗試創建圖像時,當該圖像應具有該圖像時,它會給我錯誤消息。 它還返回模型無效。

當我刪除Required時,它可以工作,但也可以將其設置為null,這是我不想要的。

關於堆棧溢出的話題似乎並不多。

這是我的模特

[Key]
public int InvoiceId { get; set; }

[Required(ErrorMessage = "Company is required")]
public string Company { get; set; }

[Required(ErrorMessage = "Description is required")]
public string Description { get; set; }

[Required(ErrorMessage = "Amount is required")]
public decimal Amount { get; set; }

[Required(ErrorMessage = "Picture of Invoice Required")]
public byte[] PictureOfInvoice { get; set; }

而我的控制器:

[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Parish Admin, Priest, Administrator")]
public ActionResult Create([Bind(Include = "InvoiceId,Company,Description,Amount,PictureOfInvoice,DateReceived,ChurchId")] Invoice invoice,HttpPostedFileBase File)
{
    if (ModelState.IsValid)
    {
        if (File != null && File.ContentLength > 0)
        {                   
            invoice.PictureOfInvoice = new byte[File.ContentLength];
            File.InputStream.Read(invoice.PictureOfInvoice, 0, File.ContentLength);

        }
        else
        {
            TempData["Error"] = "Upload an Image";
        }

        db.Invoices.Add(invoice);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    ViewBag.ChurchId = new SelectList(db.Churches, "ChurchId", "Name", invoice.ChurchId);
    return View(invoice);
}

我的視圖以防萬一

<h2>Add New Invoice</h2>

@if (TempData["Error"] != null)
{
    <div style="color:red">@TempData["Error"]</div>
}

@using (Html.BeginForm("Create", "Invoices", FormMethod.Post, new { @class = "form-horizontal", enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Company, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Company, new { htmlAttributes = new { @class = "form-control", style = "width:20em;" } })
                @Html.ValidationMessageFor(model => model.Company, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Amount, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Amount,new { htmlAttributes = new { @class = "form-control", style = "width:20em;" } })
                @Html.ValidationMessageFor(model => model.Amount, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.DateReceived, "DateRecieved", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.DateReceived, new { htmlAttributes = new { @class = "form-control", style = "width:20em;" } })
                @Html.ValidationMessageFor(model => model.DateReceived, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextBoxFor(model => model.Description, new { htmlAttributes = new { @class = "form-control", style = "width:20em;" } })
                @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.PictureOfInvoice, "Picture of Invoice", htmlAttributes: new { @class = "control-label col-md-2"})
            <div class="col-md-10">
                <input type="file" name="File" id="File" style="width: 50%;" />
                @Html.ValidationMessageFor(model => model.PictureOfInvoice, "", new { @class = "text-danger" })
                <output id="list"></output>
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ChurchId, "Church Name", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownList("ChurchId", null, htmlAttributes: new { @class = "form-control", style = "width:20em;" })
                @Html.ValidationMessageFor(model => model.ChurchId, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    <u>
        @Html.ActionLink("Back to List", "Index")
    </u>
</div>


<script src="~/Scripts/jquery.datetimepicker.js"></script>

<script>
    $('#DateReceived').datetimepicker({
        format: 'd/m/Y',
        weeks: true,
        disableWeekDays: [0, 1, 3, 4, 5, 6],
        timepicker: false,
        inline: false
    });

    function handleFileSelect(evt) {
        var files = evt.target.files; // FileList object

        // Loop through the FileList and render image files as thumbnails.
        for (var i = 0, f; f = files[i]; i++) {

            // Only process image files.
            if (!f.type.match('image.*')) {
                continue;
            }

            var reader = new FileReader();

            // Closure to capture the file information.
            reader.onload = (function (theFile) {
                return function (e) {
                    // Render thumbnail.
                    var span = document.createElement('span');
                    span.innerHTML = ['<img class="thumb" src="', e.target.result,
                        '" title="', escape(theFile.name), '"/>'
                    ].join('');
                    document.getElementById('list').insertBefore(span, null);
                };
            })(f);

            // Read in the image file as a data URL.
            reader.readAsDataURL(f);
        }
    }

    document.getElementById('File').addEventListener('change', handleFileSelect, false);
</script>

這里混合的關注是導致問題的原因。 看來您正在嘗試將實體用作視圖的模型,並使其同時滿足UI驗證和持久性驗證。

將兩個問題分開。

創建特定於視圖所需行為的視圖模型。 該模型還應包括IEnumerable<SelectListItem> ChurchList屬性以填充下拉列表。

public class CreateInvoiceViewModel {

    [Required(ErrorMessage = "Company is required")]
    public string Company { get; set; }

    [Required(ErrorMessage = "Description is required")]
    public string Description { get; set; }

    [Required(ErrorMessage = "Amount is required")]
    public decimal Amount { get; set; }

    [Required(ErrorMessage = "Picture of Invoice Required")]
    public HttpPostedFileBase File { get; set; }

    public int ChurchId { get; set; }

    public IEnumerable<SelectListItem> ChurchList { get; set; }

    //...other properties
}

並將其設置為視圖的模型

@model CreateInvoiceViewModel

如果創建新發票,則尚未分配ID。 這意味着當發布當前模型時,模型狀態不能有效,因為InvoiceId不會被標記為Required

上傳的文件(發票圖片)也應包含在視圖模型中,並應使用@Html.TextBoxFor(m => m.File, new { type = "file" })獲得客戶端驗證。 模型綁定器將根據是否提供匹配的輸入來設置該屬性。

<div class="form-group">
    @Html.LabelFor(model => model.File, "Picture of Invoice", htmlAttributes: new { @class = "control-label col-md-2"})
    <div class="col-md-10">            
        @Html.TextBoxFor(model => model.File, new { type = "file", style = "width: 50%;"})
        @Html.ValidationMessageFor(model => model.File, "", new { @class = "text-danger" })
        <output id="list"></output>
    </div>
</div>

<div class="form-group">
    @Html.LabelFor(model => model.ChurchId, "Church Name", htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.DropDownListFor(model => model.ChurchId, (IEnumerable<SelectListItem>)@Model.ChurchList, htmlAttributes: new { @class = "form-control", style = "width:20em;" })
        @Html.ValidationMessageFor(model => model.ChurchId, "", new { @class = "text-danger" })
    </div>
</div>

因此,現在在控制器端,應刪除[Bind]因為在使用視圖模型時不需要使用[Bind]

[HttpGet]
[Authorize(Roles = "Parish Admin, Priest, Administrator")]
public ActionResult Create() {
    var model = new CreateInvoiceViewModel {
        //set default property values as needed
    };

    model.ChurchList = new SelectList(db.Churches, "ChurchId", "Name");

    //...

    return View(model);
}

[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Parish Admin, Priest, Administrator")]
public ActionResult Create(CreateInvoiceViewModel model) {
    if (ModelState.IsValid) {
        var file = model.File;
        //copy properties over to entity
        var invoice = new Invoice {
            Company = model.Company,
            Description = model.Description,
            Amount = model.Amount,
            DateReceived = model.DateReceived,
            ChurchId = model.ChurchId,
            //create array for file contents
            PictureOfInvoice = new byte[file.ContentLength]
        };
        //populate byte array
        file.InputStream.Read(invoice.PictureOfInvoice, 0, file.ContentLength);

        db.Invoices.Add(invoice);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    //if we get this far model state is invalid.
    //return view with validation errors.
    model.ChurchList = new SelectList(db.Churches, "ChurchId", "Name", model.ChurchId);
    return View(model);
}

如果模型要求無效,則模型狀態將提供必要的反饋。 無需使用臨時數據和文件檢查。

您沒有在模型中使用數據綁定來填充PictureOfInvoice ,而是在控制器的方法中進行的。 但是,只有確認模型有效之后才執行該步驟,而根據此邏輯,模型將無效。

我認為您可以嘗試僅切換前幾位:

[HttpPost]
[ValidateAntiForgeryToken]
[Authorize(Roles = "Parish Admin, Priest, Administrator")]
public ActionResult Create(
[Bind(Include = "InvoiceId,Company,Description,Amount,DateReceived,ChurchId")]
     Invoice invoice,
     HttpPostedFileBase File)
{
    if (invoice!=null && File != null && File.ContentLength > 0)
    {                   
        invoice.PictureOfInvoice = new byte[File.ContentLength];
        File.InputStream.Read(invoice.PictureOfInvoice, 0, File.ContentLength);
    }
    if (ModelState.IsValid)
    {
        //Proceed

如果仍然不能讓模型通過驗證,那么您可能必須像以前在else繼續應用錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM