ASP. NET CORE, у модели View все поля равны нулю при передаче обратно в контроллер - PullRequest
2 голосов
/ 12 апреля 2020

Я пытаюсь запустить простое ASP. NET веб-приложение CORE, и у меня возникают проблемы с предоставлением пользователю доступа к файлу на моем сервере по ссылке html. У меня есть модель под названием «TestModel», представление под названием «TestView» и контроллер под названием «AppController». Мой взгляд позволяет пользователю вводить некоторый текст в два отдельных поля, а также выбирать два разных файла со своего жесткого диска, он привязывает все к моей модели и выполняет POST, когда пользователь нажимает кнопку. Я проверил, что модель правильно передается обратно моему контроллеру. Мой контроллер правильно сохраняет файлы в папке в моей директории сервера, использует отдельную службу для манипулирования файлами и возвращает модель обратно в представление, т.е. когда я использую отладчик для проверки «возвратного представления (модель)» в Testview В действии передаваемая модель имеет все свои свойства.

Проблема в том, что я хочу, чтобы две ссылки в представлении указывали на файлы на сервере, чтобы пользователь мог щелкнуть ссылку и получить приглашение для загрузки файлов, но я не могу получить это происходит. Я использую способность @ Html .ActionLink () в бритве, чтобы указать на действие «Загрузить описания» и передать ему модель, думая, что она будет передавать модель текущего представления, но модель, в которой она проходит, имеет все поля как ноль. Любое понимание того, что я делаю неправильно?

Это соответствующие действия в моем AppController:

        [HttpPost("~/App/TestView")]
        public IActionResult TestView(TestModel Model)
        {
            if (ModelState.IsValid)
            {
                Console.WriteLine("Something was sent back from the TestView page");
                Model.OnPostAsync();
                var x = _descLogicService.Convert(Model);
            }

            return View(Model);
        }

        public IActionResult DownloadDescriptions(TestModel model)
        {
            var cd = new ContentDispositionHeaderValue("attachment")
            {
                FileNameStar = model.DescriptionFile.FileName
            };

            Response.Headers.Add(HeaderNames.ContentDisposition, cd.ToString());

            byte[] bytes = System.IO.File.ReadAllBytes(model.MeasurementExportFile);

            using (FileStream fs = new FileStream(model.MeasurementExportFile, FileMode.Open, FileAccess.Read))
            {
                fs.Read(bytes, 0, System.Convert.ToInt32(fs.Length));
                fs.Close();
            }

            return File(bytes, "text/csv");

        }

Вот моя модель представления:

 public class TestModel
    {
        [BindProperty]
        [Required]
        [MinLength(5)]
        public string Name { get; set; }
        [BindProperty]
        [Required]
        [MaxLength(10,ErrorMessage ="Input string is too long.")]
        public string MyInput { get; set; }

        [BindProperty]
        [Required]
        public IFormFile DescriptionFile { get; set; }


        [BindProperty]
        [Required]
        public IFormFile MeasurementFile { get; set; }
        public string DescriptionDirectory { get; set; } 
        public string DescriptionExportFile { get; set; } 
        public string MeasurementDirectory { get; set; } 
        public string MeasurementExportFile { get; set; }

        public async Task OnPostAsync()
        {
            var token = DateTime.Now.Ticks.ToString();

            var directory =  Directory.CreateDirectory(@"uploads\"+ token + @"\");
            DescriptionDirectory = directory.CreateSubdirectory("Descriptions").FullName + @"\";
            DescriptionExportFile = directory.CreateSubdirectory(@"Descriptions\Exports\").FullName + DescriptionFile.FileName;
            MeasurementDirectory = directory.CreateSubdirectory("Measurements").FullName + @"\";
            MeasurementExportFile = directory.CreateSubdirectory(@"Measurements\Exports\").FullName + MeasurementFile.FileName;

            var file = Path.Combine(DescriptionDirectory, DescriptionFile.FileName);
            using (var fileStream = new FileStream(file, FileMode.Create))
            {
                await DescriptionFile.CopyToAsync(fileStream).ConfigureAwait(true);
            }

             file = Path.Combine(MeasurementDirectory, MeasurementFile.FileName);
            using (var fileStream = new FileStream(file, FileMode.Create))
            {
                await MeasurementFile.CopyToAsync(fileStream).ConfigureAwait(true);
            }
        }
    }

А вот вид:

@**I need to add the namespace of C# models I'm creating *@
@using FirstASPNETCOREProject.ViewModels
@*I need to identify the model which 'fits' this page, that is the properties of the model can be
    bound to entities on the view page, using "asp-for"*@
@model TestModel
@{
    ViewData["Title"] = "Page for File Uploads";
}
@section Scripts{
}

<div asp-validation-summary="ModelOnly" style="color:white"></div>
<form method="post" enctype="multipart/form-data">
    <label>Enter a Description File Name</label>
    <input asp-for="Name" type="text" />
    <span asp-validation-for="Name"></span>
    <br>
    <label>Select a Description File</label>
    <input asp-for="DescriptionFile" type="file" />
    <span asp-validation-for="DescriptionFile"></span>
    <br>
    <label>Enter the Measurement File Name</label>
    <input asp-for="MyInput" type="text">
    <span asp-validation-for="MyInput"></span>
    <br>
    <label>Select a Measurement File</label>
    <input asp-for="MeasurementFile" type="file">
    <span asp-validation-for="MeasurementFile"></span>
    <br>
    <input type="submit" value="Send Message" />
</form>


@Html.ActionLink("Description File", "DownloadDescriptions", "App")
@Html.ActionLink("Measurement File", "DownloadMeasurements", "App")

1 Ответ

1 голос
/ 12 апреля 2020

ActionLinks - это просто теги привязки.

Поэтому они используют GET. Таким образом, для возврата вашей модели с использованием get вам нужно будет использовать параметры Query String, например, добавив «? MyInpu = некоторый классный ввод» в конце URL.

Вы можете связать почти ЛЮБОЙ сложный объект, как этот, включая списки и массивы.

Для получения дополнительной информации о Привязка модели

Сам файл, которым вы не будете в состоянии передать это так. Для этого вам нужно будет отправить форму с помощью кнопки отправки или FormData, используя javascript.

Вы также можете добавить якоря, которые вызывают функции javascript, которые используют AJAX для отправки всего, что вы хотите в Действие DownloadDescription в вашем контроллере.

Вот пример того, как передать модель, используя ссылку действия:

 @Html.ActionLink("Test Action", "TestAction", "Home", new { myInput = "Some Cool Input" })

В моем случае предыдущий ActionLink создает тег привязки с href, установленным в :

http://localhost:64941/Home/TestAction?myInput=Some Cool Input

Обратите внимание, как я использовал анонимный тип для передачи модели, используя в этом случае те же имена свойств моей модели MyInput , но в верблюжьей версии myInput .

Вы можете создать любую модель, подобную этой.

Это мое действие в моем контроллере:

    public IActionResult TestAction([FromQuery]TestModel input) 
    {
        return View(input);
    }

Обратите внимание, как я использовал [FromQuery] для * Параметр 1032 * TestModel указывает на то, что я ожидаю, что механизм связывания базовой модели ASP. NET будет использовать параметры строки запроса для заполнения моей модели.

Это мой класс модели:

public class TestModel
{
    public string MyInput { get; set; }
}

Это результат во время отладки:

enter image description here

Обратите внимание, что во время отладки я вижу заполненное значение.

ПРИМЕЧАНИЯ:

Если ваша модель меняется на стороне клиента. Вам нужно будет обновить параметры строки запроса в теге привязки, используя javascript ..., по этой причине рекомендуется добавить имя в тег привязки.

Также это может ответить на ваш вопрос, но НЕ может будь лучшим подходом к тому, что ты пытаешься сделать.

...