-1

i am using view model to upload multiple videos but the videos are not uploading. before using the view model code working fines but now when i click on upload button and debug then the video object in HTTP post action of upload is null here is my code of controller

public ActionResult UploadedVideos()
{
    ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
    var q = db.Videos.Where(v => v.UserId == user.Id).ToList();
    return View(q);
}

[HttpPost]
public ActionResult Upload(List<Models.ViewModels.VideoView> videos)
{
    try
    {
        ApplicationUser user =    System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
        HttpFileCollectionBase files = Request.Files;
        //  Video video = new Video();
        foreach (var video in videos)
        {
            long time = DateTime.Now.Ticks;
            string path = Server.MapPath("~/Images/" + time + "_" + video.file.FileName);
            video.file.SaveAs(path);
            video.Path = path;
            video.DateTimeStamp = DateTime.Now;
            video.UserId = user.Id;
            db.Videos.Add(video);
        }
        db.SaveChanges();
        return RedirectToAction("UploadedVideos");
    }
    catch(Exception e)
    {
        return Json("Failed Error : "+e.Message,       JsonRequestBehavior.AllowGet);

     }
 }

and the code of view is

@model Final.Models.ViewModels.VideoView
@{
    ViewBag.Title = "upload";
}
<h2>Index</h2>
@using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{

    @Html.AntiForgeryToken()

    <div class="form-horizontal">

        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control inputField" } })
                @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Category, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Category, new { htmlAttributes = new { @class = "form-control inputField" } })
                @Html.ValidationMessageFor(model => model.Category, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Tags, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Tags, new { htmlAttributes = new { @class = "form-control inputField" } })
                @Html.ValidationMessageFor(model => model.Tags, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.PrivacyStatus, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.PrivacyStatus, new { htmlAttributes = new { @class = "form-control inputField" } })
                @Html.ValidationMessageFor(model => model.PrivacyStatus, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.TextAreaFor(model => model.Description, new { @cols = "50", @rows = "5" })
                @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-horizontal">

            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control inputField" } })
                    @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.Category, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Category, new { htmlAttributes = new { @class = "form-control inputField" } })
                    @Html.ValidationMessageFor(model => model.Category, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.Tags, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Tags, new { htmlAttributes = new { @class = "form-control inputField" } })
                    @Html.ValidationMessageFor(model => model.Tags, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.PrivacyStatus, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.PrivacyStatus, new { htmlAttributes = new { @class = "form-control inputField" } })
                    @Html.ValidationMessageFor(model => model.PrivacyStatus, "", new { @class = "text-danger" })
                </div>
            </div>
            <div class="form-group">
                @Html.LabelFor(model => model.Description, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.TextAreaFor(model => model.Description, new { @cols = "50", @rows = "5" })
                    @Html.ValidationMessageFor(model => model.Description, "", new { @class = "text-danger" })
                </div>
            </div>
            </div>

            <div class="form-group">
                <div class="col-md-offset-2 col-md-10">
                </div>
                <div class="form-group">
                    <input type="file" name="file" multiple id="file" /><br />

                    <div id="all-progress-bars"></div>
                    <input type="submit" value="Save and Upload" href="javascript:void(0)" id="bb" class="btn btn-default" />


                    <span id="display"></span>
                </div>
            </div>
        </div>
}

and this is my viewmodel

public class VideoView:Video 
{
    public HttpPostedFileBase file { get; set; }
}
Arslan Afzal
  • 95
  • 2
  • 13
  • [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) –  Mar 16 '16 at 10:10
  • The model in the view is `VideoView` but you POST method is `IEnumerable` so it will never bind. - If you want to upload multiple files, then the property needs to be `public IEnumerable file { get; set; }` –  Mar 16 '16 at 10:47
  • @StephenMuecke thank you but now a new error is occur in controller can you please look at it ? – Arslan Afzal Mar 16 '16 at 15:43
  • @StephenMuecke thank you but now a new error is occur in controller can you please look at it ? it says in post function of upload that **IEnumerable does not contain a definition for 'SaveAs' and no extension for 'SaveAs'.** and same error occur at ' string path = Server.MapPath("~/Images/" + time + "_" + video.file.FileName);' here FIleName shows same error as **SaveAs** does do you know what is for ? – Arslan Afzal Mar 16 '16 at 15:50
  • Because you need to loop each file in the collection - `foreach (var video in files) { // save each file }` –  Mar 16 '16 at 21:08
  • **foreach(var video in videos )** i a already doing this you can see above but the error remain sames even if i replace **videos with files** @StephenMuecke – Arslan Afzal Mar 17 '16 at 04:44
  • No - `video` is type of `HttpPostedFileBase` - so to save it you need `video.SaveAs(path);`, not `video.file.SaveAs(path);` –  Mar 17 '16 at 04:46
  • ok i did it as you stated above but same error occurs still @StephenMuecke – Arslan Afzal Mar 17 '16 at 05:02
  • You cant of done what I said or you would never get that error. Edit your question by adding the new code you tried to the end of it. And in future do not just dump all you code into the question. I have edited the controller, but you should still edit the view code to include only what is relevant –  Mar 17 '16 at 05:10
  • And looking at your view, why on earth do you have 2 `@Html.ValidationSummary` and repeated all the form controls again (the second lot will all be ignored) –  Mar 17 '16 at 05:14
  • And you GET method would be throwing an exception since in returns `List –  Mar 17 '16 at 05:15
  • i repeated all the form 2 times because i want to upload multiple videos with description every video should have attributes like title, category, tags and description so for the sake of testing i repeat it for two times and upload two files – Arslan Afzal Mar 17 '16 at 06:00
  • You cannot do that - only the first one would ever be bound. But as I noted, you have shown the wrong code anyway because you would be throwing an exception before the view was even rendered. –  Mar 17 '16 at 06:01
  • Note also I have rolled back your changes. You cannot change the original question. If you want to show new code you have tried, append it as I noted previously. –  Mar 17 '16 at 06:15
  • no this is the code exactly which i was using and you are right its throwing an exception as i stated earlier that when i introduce View Model the exceptions and errors are occur any how thank you so much for your concern and the second thing is i am new in asp.net so can you please tell me the way how can i do this ? i actually want to upload at least five videos at a time and every video should have it owns attributes like title, tags etc etc and this attributes are mandatory because i want to use these attributes in API please some piece of help would highly appreciated – Arslan Afzal Mar 17 '16 at 06:22
  • Will add answer in 30 min or so. But I don't get the point of returning a list of existing video to the view if you wanting to upload new videos? Do you want to create 5 new videos (with those additional properties) of do you want to edit the properties of existing videos? –  Mar 17 '16 at 06:25
  • i am passing the list of videos which are uploaded from the user and user can just edit their attributes not the videos after uploading. and if user want to add new videos then he will enter new attribute every video has it's own attribute and user can select 5 videos at a time for upload and every video has it's own attributes – Arslan Afzal Mar 17 '16 at 06:32
  • You are going to have to do this using 2 views (at least to start with or the code will run into many pages). One to upload new videos and one to edit the properties of existing videos. –  Mar 17 '16 at 06:35
  • yep i already have two views one for uploaded videos action and one for upload video action – Arslan Afzal Mar 17 '16 at 06:41
  • So do you want the solution to add new videos and their properties? –  Mar 17 '16 at 06:42
  • if you have any account email account and if you share it with me then i will send you my project which if its comfortable with you not necessary – Arslan Afzal Mar 17 '16 at 06:43
  • yes i want solution for add new videos and their properties – Arslan Afzal Mar 17 '16 at 06:44
  • Sorry, but I don't do that. But I am happy to add an answer here. Give me 30 min or so. –  Mar 17 '16 at 06:45
  • but one thing i want t upload multiple videos at concurrent time from a user at least 5 videos. not one by one – Arslan Afzal Mar 17 '16 at 06:45
  • no problem :) thank you for your concern – Arslan Afzal Mar 17 '16 at 06:46

1 Answers1

0

If you want a user to upload multiple videos including adding properties for each video, you need to start with a view model representing wantyou want to edit

public class VideoVM
{
    public string Title { get; set; }
    public string Description { get; set; }
    .... // other properties as required
    public HttpPostedFileBase File { get; set; }
}

and in the GET method, create a collection to pass to the view

public ActionResult Upload()
{
    List<VideoVM> model = new List<VideoVM>();
    for (int i = 0; i < 5; i++)
    {
        model.Add(new VideoVM());
    }
    return View(model);
}

and the view will be

@model List<VideoVM>
....
@using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    for(int i = 0; i < Model.Count; i++)
    {
        @Html.TextBoxFor(m => m[i].Title)
        @Html.TextBoxFor(m => m[i].Description)
        ....
        @Html.TextBoxFor(m => m[i].File, new { @type = "file" })
    }
    <input type="submit" value="Upload" />
}

which will post back to

[HttpPost]
public ActionResult Upload(List<VideoVM> model)
{
    foreach(VideoVM video in model)
    {
        if (video.File.ContentLength > 0)
        {
            continue;
        }
        string fileName = Path.GetFileName(video.File.FileName);
        string path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
        video.File.SaveAs(path);
        Video dataModel = new Video()
        {
            Title = video.Title,
            Description = video.Description,
            ....
            Path = path
        };
        db.Videos.Add(dataModel);
    }
    db.SaveChanges();
    return RedirectToAction("UploadedVideos");
}

Side note: You have noted in the comments that you want a user to upload up to 5 videos. The above code creates all 5. If you want to allow less than 5 to be added (and assuming you have validation attributes on your properties), then you need javascript to dynamically add the html for each item and update the collection indexers. For examples of how to implement this, refer to the following questions/answers

Community
  • 1
  • 1
  • A few extra notes: Your model should have both a `FileDisplayName` and a `FilePath` property. The first one being for the actual file name the user uploaded (when you edit existing videos, you want the user to see the file name they uploaded, not some long path with directories and `Ticks`) and the second for the path. And it would be better to save the file using a `Guid` rather than trying to perpend some value based on `Ticks` –  Mar 17 '16 at 07:29
  • this is very helpful thank you so much and i am grateful to you. – Arslan Afzal Mar 17 '16 at 08:45