Question

I'm trying to upload file using ASP .NET MVC 4. I followed exactly these instructions, but when I submit file I always find myself in the wrong Index method (though that renders the form). My code:

Controller:

public class ActivationController : Controller
{
    public ViewResult Index()
    {
        return View(new ActivationIndexViewModel());
    }

    [HttpPost]
    public ActionResult Index(HttpPostedFileBase file)
    {
        // NEVER GET HERE!
        if (file != null && file.ContentLength > 0)
        {
            var fileName = Path.GetFileName(file.FileName);
            var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
            file.SaveAs(path);
        }
        return RedirectToAction("Index");  
    }
}

View:

<form class="form-horizontal" role="form">
<div class="container-fluid">
    <div class="row">
        <div class="form-group">
            <label class="col-sm-2 control-label" for="file">Serial number</label>
            <div class="col-sm-10">
                @using (Html.BeginForm("Index", "Activation", FormMethod.Post, new { enctype = "multipart/form-data" }))
                {
                    <input type="file" name="file" />
                    <input type="submit" value="Load" class="btn btn-primary" />
                    <p class="help-block">Select a file</p>
                }
            </div>
        </div>
    </div>
    <div class="row">
        <div class="form-group">
            <label class="col-sm-2 control-label">Продукт</label>
            <div class="col-sm-10">
                @Html.DropDownListFor(m => m.SelectedProductId,
                    @Model.ActivatableProductsAsSelectList, new { @class = "form-control" })
                <p class="help-block">Select a product</p>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="form-group">
            <label class="col-sm-2 control-label">Options</label>
            <div class="col-sm-10">
                 <div class="table-responsive">
                    <table class="table"/>
                </div>
            </div>
        </div>
    </div>
</div>

RouteConfig:

routes.MapRoute(
           name: "Activation",
           url: "{controller}/{action}",
           defaults: new { controller = "Activation", action = "Index" }
       );

What am I doing wrong?

Was it helpful?

Solution

Ok, I identified the problem. Problem is your nested forms. Submit button will always post your parent form, and your parent form doesn't have a action,method or anything defined. So it is hitting index again and again.

Simple solution is to remove outer form, or replace the outer form with inner form. Other options is to use AJAX forms, but do not nest them.

Have your view like this -

@using (Html.BeginForm("Index", "Activation", FormMethod.Post, new { enctype = "multipart/form-data", id = "Form1" }))
{
    <div class="container-fluid">
        <div class="row">
            <div class="form-group">
                <label class="col-sm-2 control-label" for="file">Serial number</label>
                <div class="col-sm-10">

                    <input type="file" name="file" />
                    <input type="submit" value="Load" class="btn btn-primary" />
                    <p class="help-block">Select a file</p>

                </div>
            </div>
        </div>
        <div class="row">
            <div class="form-group">
                <label class="col-sm-2 control-label">Продукт</label>
                <div class="col-sm-10">
                    @Html.DropDownListFor(m => m.SelectedProductId, new SelectList(Model.ActivatableProductsAsSelectList, "Value", "Text"), "Select", new { @class = "form-control" })
                    <p class="help-block">Select a product</p>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="form-group">
                <label class="col-sm-2 control-label">Options</label>
                <div class="col-sm-10">
                    <div class="table-responsive">
                        <table class="table" />
                    </div>
                </div>
            </div>
        </div>
    </div>
}

Then your controller action is -

    [HttpPost]
    public ActionResult Index(ActivationIndexViewModel model, HttpPostedFileBase file)
    {
        // NEVER GET HERE!
        if (file != null && file.ContentLength > 0)
        {
            var fileName = Path.GetFileName(file.FileName);
            var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
            file.SaveAs(path);
        }
        return RedirectToAction("Index");
    }

Output would be -

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top