Plumbus
Plumbus

Reputation: 31

String values in Model are empty

I am trying to create a custom filename for files that are uploaded to my application so they can be viewed and downloaded easily. I am having trouble with accessing the data that is supposed to be stored in my model when the controller action for upload is called and was wondering if anyone could try and help me, code for View, Controller and Model are below.

Model

    using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace FinalYearProject.Models
{
    public class UploadModel
    {
        [Required(ErrorMessage = "Course is required")]
        public string Course { get; set; }
        [Required(ErrorMessage = "Title is required")]
        public string Title { get; set; }

        public string Uploader { get; set; }
    }
}

Controller

    using System;
using System.Collections.Generic;
using System.IO;
using Project.Models;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Project.Controllers
{
    public class FileController : Controller
    {

        [Authorize(Roles = "Admin, Lecturer")]
        public ActionResult Index()
        {
            return View(new UploadModel());
        }

        [HttpPost]
        [Authorize(Roles = "Admin, Lecturer")]
        public ActionResult Index([Bind(Include = "Course,Title")] UploadModel testing)
        {


            if (ModelState.IsValid)
            {
                foreach (string upload in Request.Files)
                {

                    if (Request.Files[upload].FileName != "")
                    {
                        string path = AppDomain.CurrentDomain.BaseDirectory + "/App_Data/uploads/";
                        string filename = Path.GetFileName(Request.Files[upload].FileName);
                        //string newfilename = Path.GetFileName((testing.Title + " - " + testing.Course) + "." + "pdf");
                        Request.Files[upload].SaveAs(Path.Combine(path, filename));
                    }
                }
                return RedirectToAction("Index");
            }
            //You can use model.Course and model.Title values now

            return View(testing);
        }


        [Authorize(Roles = "Admin, Lecturer, Student")]
        public ActionResult Downloads()
        {
            var dir = new System.IO.DirectoryInfo(Server.MapPath("~/App_Data/uploads/"));
            System.IO.FileInfo[] fileNames = dir.GetFiles("*.*"); List<string> items = new List<string>();
            foreach (var file in fileNames)
            {
                items.Add(file.Name);
            }
            return View(items);
        }
        public FileResult Download(string FileName)
        {
            var FileVirtualPath = "~/App_Data/uploads/" + FileName;
            return File(FileVirtualPath, "application/force-download", Path.GetFileName(FileVirtualPath));
        }
    }
}

View

@using Project.Models;
@using Project.Controllers

@model UploadModel


@{
    ViewBag.Title = "Upload";
    Layout = "~/Views/Shared/_Layout.cshtml";
    var courses = ForumController.checkCourseList;
}

<link href="~/Content/sweetalert.css" rel="stylesheet" />

<h2>Upload Content</h2>

@section scripts {
    <script src="~/Scripts/jquery-1.10.2.min.js"></script>
    <script src="~/Content/sweetalert.min.js"></script>
    <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
    <script>
        $(document).ready(function () {
            $('#btnUploadFile').click(function () {
                var data = new FormData();
                var files = $("#fileUpload").get(0).files;

                if (files.length > 0) {
                    data.append("UploadedFile", files[0]);
                }



                var ajaxRequest = $.ajax({
                    type: "POST",
                    url: "File/Index",
                    contentType: false,
                    processData: false,
                    success: function () {
                        swal({
                            type: "success",
                            title: "Uploaded",
                            text: "The file has been uploaded",
                            timer: 2000,
                            showConfirmButton: false
                        });
                    },
                    error: function () {
                        swal({
                            type: "error",
                            title: "Error",
                            text: "Something went wrong, please try again!",
                            timer: 2000,
                            showConfirmButton: false
                        });
                    },
                    data: data
                });
                ajaxRequest.done(function (xhr, textStatus) {

                });

            });
        });
    </script>
    }

@using (Html.BeginForm())
{
    <div class="uploadContainer">
        <table>


            <tr>
                <td>Title :</td>
                <td colspan="2" class="editUploadTitle">
                    @Html.TextBoxFor(m => m.Title, new { @class = "uploadTitleInp" })
                    @Html.ValidationMessageFor(m => m.Title)
                </td>
            </tr>

            <tr>
                <td>Course :</td>
                <td>
                    @{
                        List<SelectListItem> listItems = new List<SelectListItem>();
                        foreach (var course in courses)
                        {
                            listItems.Add(new SelectListItem
                            {
                                Text = course .Courses.Name,
                                Value = course .Courses.Name
                            });
                        }
                    }

                    @Html.DropDownListFor(m => m.Course, listItems, "-- Select Course--")

                    @Html.ValidationMessageFor(m => m.Course)
                </td>
            </tr>

            <tr>
                <td>File :</td>
                <td>
                    <input type="file" name="FileUpload1" id="fileUpload" required />
                </td>
            </tr>

            <tr>
                <td></td>
                <td>
                    <input id="btnUploadFile" type="button" value="Upload File" />
                </td>
            </tr>

        </table>

    </div>
                        }




@Html.ActionLink("View Uploads", "Downloads")

When I try to create a custom file name using : string newfilename = Path.GetFileName((testing.Title + " - " + testing.Course) + "." + "pdf"); The course and the title for the upload that are entered in the view are represented as empty strings, I'm not quite sure why this is and any help would be greatly appreciated.

Upvotes: 0

Views: 100

Answers (2)

Usman
Usman

Reputation: 4703

you are adding file upload in data but not the values of Title and Course

var data = new FormData();
var files = $("#fileUpload").get(0).files;

if (files.length > 0) {
 data.append("UploadedFile", files[0]);
 }
data.append("Title", $('#Title').val());
data.append("Course", $('#Course').val());

you have to append values of your title and course along with file

Upvotes: 0

Chris Pratt
Chris Pratt

Reputation: 239290

Nothing is jumping out at me as an obvious cause for these two properties to be blank. However, there's a number of things wrong with your code here, so perhaps fixing those will fix this issue as well.

  1. You're using Html.BeginForm() with no parameters. In order to have file uploads your form must have enctype="multipart/form-data". That would require:

    @using (Html.BeginForm("Action", "Controller", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
    

    Or, you can simply use a form tag directly:

    <form action="" method="post" enctype="multipart/form-data">
    
  2. The whole point of using a view model is to give the view only what it needs to work with. As such, using Bind in conjunction with a view model makes no sense. Remove your Bind attribute from the action, and if Uploader shouldn't be available to be posted to, remove it from your view model. You're most likely setting this directly on the entity, anyways, via something like User.Identity.Name. If you want it available for display, but don't want people to be able to post to it, you can simply mark the property with [ReadOnly]. However, since you're responsible for creating the eventual entity this would be stored to, you simply would not map this value over.

  3. You're making you're life harder by not utilizing your view model for the actual file uploads. Add a property to your view model like:

    [DataType(DataType.Upload)]
    public HttpPostedFileBase FileUpload { get; set; }
    

    Then, you can work with this property on your model directly without delving into Request.Files.

Upvotes: 1

Related Questions