0

嗨,我有一个这样的控制器:

public class MyController : Controller
    {
        public MyController(Uow uow)
        {
            ;
        }

        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(HttpPostedFileBase file)
        {
            var validationResults = _uow.GetResults(file.FileName, file.InputStream);

            return View(new MyViewModel { Errors = validationResults.Errors, Data = validationResults.Data });
        }

        [HttpPost]
        public void Save(MyViewModel viewModel)
        {
            //Save the data
        }
    }

这有一个像这样的视图:

@model MyViewModel 

<form action="" method="post" enctype="multipart/form-data">

    <label for="file" id="filelabel">Filename:</label>
    <input type="file" name="file" id="file" />

    <input type="submit" id="submitbtn" disabled="disabled" />
    <img class="loader" id="loader" style="display: none;" alt="Loading..." src="@Url.Content("~/Content/Images/ajax-loader.gif")" />

    @if (Model != null && Model.Errors.Any())
    {
        foreach (var error in Model.Errors)
        {
            <span class="error">@error</span>
        }    
    }

    <button id="savebtn" >Save</button>

</form>


<script type="text/javascript">

    $(document).ready(function () {

        $('#file').change(function () {
            alert("in here");
            $('#submitbtn').prop('disabled', false);

        });

        $('#submitbtn').click(function () {

            $('#loader').show();

        });

    });
</script>

所以我在这里想要的是一种将文件上传到控制器的方法。我已经实现了这一点,并在 Index Post 中收到了它。然后我处理这个工作正常。然后我将相关数据放入 viewModel 并重新显示表单。

我想要的是,当按下 Save 按钮时,会使用填充的 viewModel 调用 Save Post 方法。但是,每当我按下按钮时,它都会发布到 Index Post,这是有道理的。

有人可以告诉我如何保留我的文件上传和处理代码,但是当我稍后按下 Save 按钮时,viewModel 会发送到 Save Post 方法?

4

1 回答 1

0

如果您必须将这些操作分开并且不更改当前表单,那么您将需要一个单独的表单才能异步发布或不发布到其他操作......这意味着做一些讨厌的事情,比如使用 javascript 更新另一个表单中的隐藏字段每当对第一个表单进行更改...这不是万无一失的,因为可以通过多种方式更改表单字段而无需触发某些 javascript 事件。

当单击保存按钮时,也有可能使用 javascript 更改表单操作。但老实说,这对我来说似乎太脏了,我会使用 viewmodel 到 1 操作方法。

我建议HttpPostedFileBase在您的视图模型上使用 Index 操作来处理数据的验证和保存。

有关强类型表单帮助程序和注释,请参阅此示例:如何在 asp.net mvc 3 中使用 jquery 和 dataannotation 验证输入文件

它显示了一个HttpPostedFileBase带有 的属性DataAnnotations,如果您需要以这种方式验证它,您可能想尝试编写一个调用您的 UOW 的自定义注释.. 不知道为什么?

我也建议使用 Model.ValidationMessageFor() 帮助器。

接收视图模型的操作的一般模式如下所示:

[HttpPost]
public ActionResult Index(MyViewModel myViewModel)
{
    try
    {
        // Check your viewmodel is valid
        if (!ModelState.IsValid)
        {
            // not valid so return to the view with the view model as a param
            // The validation message helpers will display the relevant error messages
            return View(myViewModel);
        }

        // modelstate is valid so perform any work i.e. save to database
        // attach any additional information to the view modal to give feedback maybe?
        // or redirect the user to some other page
        return View(myViewModel);
    }
    catch
    {
        // any exceptions then go back to the view and hopefully the validation helpers will kick in
        return View(myViewModel);
    }
}

就个人而言,我会做这种事情,但你可以明白:

在视图模型中

[DisplayName("Update your image")]
[Required]
public HttpPostedFileBase Image { get; set; }
public string ImageName { get; set; }

在视图中

@if (Model.ImageName != null) { 
    <img src="@Url.Content("~/uploads/" + Model.ImageName)" alt="" />
}

<div class="control-group">
    @Html.LabelFor(model => model.Image)
    <div class="controls">
        @Html.TextBoxFor(model => model.Image, new { @type = "file", @class = "input-file" })
        @Html.ValidationMessageFor(model => model.Image)
    </div>
</div>

在控制器发布动作中,检查后ModelState.IsValid

var fileName = "";
// check for a posted file and that it has a size to it before attempting to save the file
if (myViewModel.Image != null && myViewModel.Image.ContentLength > 0)
{
    var currentDate = DateTime.UtcNow.ToString("yyyymmddhhmmss");
    var fileType = Path.GetExtension(myViewModel.Image.FileName);
    Random random = new Random();
    fileName = Path.GetFileNameWithoutExtension(myViewModel.Image.FileName) + "-" + currentDate + random.Next(1, 10000) + fileType;

    // upload the file
    var path = Path.Combine(Server.MapPath("~/uploads"), fileName);
    myViewModel.Image.SaveAs(path);
}

// for saving to the database on an model entity
if (fileName != "")
{
    entity.ImageName = fileName;
}
于 2013-01-24T00:28:55.983 回答