Upload and Download files to server as GUID in MVC 5 with Entity Framework 6

Intelli-Seeker
Intelli-Seeker used Ask the Experts™
on
I am using ASP.NET MVC 5 with entity framework 6 and a SQL 2014 database to create a customer relationship management system. I want to add the capability to upload and download attachments to the meeting. With the code below, I have a browse button and can browse to the files, but it is not saving to the folder in the Solution and is not saving the path to the database.

In my mind, The create view of the MeetingsController creates the meeting and allows uploading attachments. The Meeting Details view shows the meeting information as well as a link to download the related attachments. This is working off of an existing database that was used for a desktop application. I want to make this a website for my end users. I used database first methodology to create the scaffolding for controllers and views.

Here is the HttpPost for the Create action in the MeetingsController:

 [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,InteractionDate,Notes,approval_status_id,CustomerCallDecisionedBy,CustomerCallDecisionDate,BankOfficer,TrustOfficer,Customer,Employee,IsDeleted,IsReview")] Meeting meeting, HttpPostedFileBase upload)

        {
            if (ModelState.IsValid)
            //Add upload capability to the create meeting view
            {
                List<Attachment> attachments = new List<Attachment>();
                for (int i = 0; i <Request.Files.Count; i++)
                {
                    var file = Request.Files[i];
                    if(file != null && file.ContentLength > 0)
                    {
                        var fileName = Path.GetFileName(file.FileName);
                        Attachment attachment = new Attachment()
                        {
                            Name = Path.GetFullPath(fileName),
                            Path = Guid.NewGuid().ToString() + Path.GetExtension(upload.FileName),
                        };
                        attachments.Add(attachment);
                        var path = Path.Combine(Server.MapPath("~/uploads"), attachment.Name + attachment.Path);
                        file.SaveAs(path);
                    }
                }
            //Add Account List to create view
                foreach (var account in db.Accounts.Where(x => x.Customer == meeting.Customer))
                {
                    var snapshot = new Snapshot
                    {
                        AccountNumber = account.AccountNumber,
                        System = account.System,
                        Category = account.Category,
                        Balance = account.Balance,
                    };

                    meeting.Snapshots.Add(snapshot);
                }
                meeting.Attachments = attachments;
                db.Meetings.Add(meeting);
                db.SaveChanges();
                return RedirectToAction("Details", new { Id = meeting.Id });
            }
                return View(meeting);
        }

Open in new window


This is the code for the MeetingModel view model. Line 110 has the control for the upload:

@model CRM.Models.MeetingModel

@{
    ViewBag.Title = "Create";
}

<h2>Create Meeting</h2>


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

    @Html.AntiForgeryToken()

    @Html.HiddenFor(x => x.Customer)

<div class="form-horizontal">
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.Customer1.Name, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Customer1.Name, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Customer1.Name, "", new { @class = "text-danger" })
        </div>
    </div>
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(model => model.InteractionDate, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.InteractionDate, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.InteractionDate, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(model => model.Purpose, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Purpose, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Purpose, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Notes, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Notes, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Notes, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(model => model.FollowUpItems, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.FollowUpItems, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.FollowUpItems, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Customer1.BankOfficer, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Customer1.BankOfficer, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Customer1.BankOfficer, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.TrustOfficer, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.TrustOfficer, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.TrustOfficer, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Employee, "Employee", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownList("Employee", null, htmlAttributes: new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.Employee, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.IsDeleted, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <div class="checkbox">
                @Html.EditorFor(model => model.IsDeleted)
                @Html.ValidationMessageFor(model => model.IsDeleted, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.ConfidenceRating, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.ConfidenceRating, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.ConfidenceRating, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.IsReview, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <div class="checkbox">
                @Html.EditorFor(model => model.IsReview)
                @Html.ValidationMessageFor(model => model.IsReview, "", new { @class = "text-danger" })
            </div>
        </div>
    </div>

    <div class="form-group">
            @Html.Label("Attachment", new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                <input type = "file" multiple="multiple" id="Attachment" name="upload">
            </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>
}
<br />
@* Get account data*@

    <div>
        <h3>
            Account Current Balance
        </h3>



        <table class="table">
            <thead>
                <tr>
                    <th scope = "col" > Account Number</th>
                    <th scope = "col" > System </ th >
                    < th scope="col">Category</th>
                    <th scope = "col" > Balance </ th >
                </ tr >
            </ thead >
            < tbody >
                @foreach(var snapshot in Model.Snapshots)
                {
                    <tr>
                        <td>@snapshot.AccountNumber</td>
                        <td>@snapshot.System</td>
                        <td>@snapshot.Category</td>
                        <td>@((snapshot.Balance ?? 0).ToString("c"))</td>
                    </tr>
                }
            </tbody>
        </table>
    </div>
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts
{
    @Scripts.Render("~/bundles/jqueryval")
}

Open in new window


This is the code for the Attachment Model:

namespace CRM.Models
{
    using System;
    using System.Collections.Generic;
    
    public partial class Attachment
    {
        public int Id { get; set; }
        public string Path { get; set; }
        public string Name { get; set; }
        public Nullable<int> Meeting { get; set; }
    
        public virtual Meeting Meeting1 { get; set; }
    }
}

Open in new window


This is the edmx diagram with the Meeting and Attachment tables. On the current database, the file is renamed to a GUID and the GUID and path are saved in the "Path" column. The name that a user assigns to the file is saved in the "Name" column in the Attachment table. One meeting can have multiple attachments.

Model Screenshot
So my question is: I have a browse button and can browse to the files, but it is not saving to the folder in the Solution and is not saving the path to the database. I am also hoping to download and retrieve files as a GUID.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Chief Technology Ninja
Distinguished Expert 2018
Commented:
Hi Intelli-Seeker,

Kindly post the updated code as discussed.

Regards,
Chinmay.

Author

Commented:
Chinmay Patel was extremely helpful in resolving my issue. I would recommend him for any project with similar issues to what I was experiencing. Here is the final code.

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "Id,InteractionDate,Notes,approval_status_id,CustomerCallDecisionedBy,CustomerCallDecisionDate,Customer,Employee,IsDeleted")] Meeting meeting, HttpPostedFileBase upload)

        {
            if (ModelState.IsValid)
            //Add upload capability to the create meeting view
            {
                List<Attachment> attachments = new List<Attachment>();
                for (int i = 0; i < Request.Files.Count; i++)
                {
                    var file = Request.Files[i];
                    if (file != null && file.ContentLength > 0)
                    {
                        var fileName = Path.GetFileName(file.FileName);
                        var id = Guid.NewGuid().ToString();
                        Attachment attachment = new Attachment()
                        {
                            Name = fileName,
                            Path = id + Path.GetExtension(upload.FileName),
                        };
                        attachments.Add(attachment);
                        var path = Path.Combine(Server.MapPath("~/uploads"), attachment.Path);
                        file.SaveAs(path);
                    }
                }
                meeting.Attachments = attachments;
                db.Meetings.Add(meeting);
                db.SaveChanges();
                return RedirectToAction("Details", new { Id = meeting.Id });
            }
            return View(meeting);
        }
    }
}

Open in new window

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial