0

Background

I have been working on a personal project creating a media player/organizer fitted with a music library, import and playlist functionality which the users can customize and add based on their needs.

Issue

Within this project, i came to the most crucial part of the application where i want to list out all the songs the user had imported into their library and or playlists allowing the ability for these to be played. I came across the below post which is exactly the issue i am facing however i do not see a clear explanation of how to resolve this issue in turn why i am creating this post.

Link to post referenced: Using .Net MVC, how can I list multiple html audio players that play different files?

I used this post to play one audio file however i am still unable to use this to play multiple.

Code

Below you can see all of my attempts within the playlist view to try and be able to allow all songs in the playlist to be playable. It seems as though the foreach loop just skips over the audio tag entirely and looks to render one media player at load time:

@model IEnumerable<WhizzyMediaOrganiser.Models.Playlist_Contents_MVC>

@{
    ViewBag.Title = "PlaylistContents";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>PlaylistContents</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.SongFilePath)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.HeaderId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.SongId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.DateAdded)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td>
                @*Not worked*@
                @*<audio controls="controls" preload="auto" src="@item.SongFilePath"></audio>*@

                @*Worked but for only audio file*@
                @*<audio controls="controls" preload="auto" src="@Url.Action("MyAudio")"></audio>*@

                @*Not worked*@
                <article class="audio">
                    <audio controls>
                        <source src="@Url.Action(item.SongFilePath)" type="audio/mp3" />
                    </audio>
                </article>
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.HeaderId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.SongId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.DateAdded)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
                @Html.ActionLink("Details", "Details", new { id = item.Id }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.Id })
            </td>
        </tr>
    }

</table>

Below is the code within the supporting controller:

public class PlaylistsController : Controller
    {
        IDbRepository rep;

        public PlaylistsController(IDbRepository rep)
        {
            this.rep = rep;
        }

        public PlaylistsController()
        :this(new DbRepository()) { }

        // GET: Playlists/Details/5
        public ActionResult PlaylistContents(int id)
        {
            var dbPlaylistContents = rep.GetPlaylistContentsByHeaderId(id);

            List<Playlist_Contents_MVC> contents = new List<Playlist_Contents_MVC>();
            foreach (var item in dbPlaylistContents)
            {
                var song = rep.GetSongById(item.SONG_ID);
                var songFile = rep.GetSongFileById(song.FILE_ID);
                Playlist_Contents_MVC content = new Playlist_Contents_MVC()
                {
                    Id = id,
                    SongFilePath = songFile.FILE,
                    SongId = item.SONG_ID,
                    DateAdded = item.DATE_ADDED,
                    HeaderId = item.HEADER_ID
                };

                contents.Add(content);
            }

            return View(contents);
        }

        //Action called by single audio file attempt
        public ActionResult MyAudio()
        {
            var file = Server.MapPath("~\\SongFiles\\benny_blanco_Halsey_Khalid_–_Eastside_official_video_.mp3");
            return File(file, "audio/mp3");
        }

Below is Playlist_Contents_MVC model (model that the view is based on):

public partial class Playlist_Contents_MVC
    {
        public string SongFilePath { get; set; }
        public int Id { get; set; }
        public int SongId { get; set; }
        public int HeaderId { get; set; }
        public DateTime DateAdded { get; set; }
    }

End Goal

Just to be more helpful in conveying what i am trying to achieve, below shows a link to images showing the playlist headers and playlist contents pages involved with the playlist functionality.

Link: https://i.stack.imgur.com/bIehl.jpg

  • The playlist headers page shows the list of all the playlists that
    the user has created with the details button taking them to its
    contents
  • The playlist contents pages shows all the songs in the playlist selected and i am trying to give the users the ability to pause, play, change the volume etc. of any song in this page by the use of the audio tag controls (or using another form of controls if needed)

Note: the app is far from finished so ignore all the poorly named columns etc.

Final comments

If anyone needs anymore clarification please let me know and i can elaborate and all suggestions are welcome.

Thanks in advance!

1 Answers1

0

You can change foreach part of your HTML this like:

@foreach (var item in Model)
{
    <tr>
        <td>                
            <article class="audio">
                <audio controls>
                    <source src="@item.SongFilePath" id="@item.Id" type="audio/mp3" />
                </audio>
            </article>
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.HeaderId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.SongId)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DateAdded)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
            @Html.ActionLink("Details", "Details", new { id = item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id = item.Id })
        </td>
    </tr>
}

Also in the controller, you should not pass the "File", it is enough that you pass the "file location" on the server (URL of the file).

please check the code. Let me know if there is more information.

Update:

Let me explain more clearly. I made this project as a sample. let's look at this. This is an HTML part:

@model IEnumerable<WebApplication1.Models.Playlist_Contents_MVC>


<h2>PlaylistContents</h2>

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.SongFilePath)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.HeaderId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.SongId)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.DateAdded)
        </th>
        <th></th>
    </tr>

    @foreach (var item in Model)
    {
        <tr>
            <td> 
                <article class="audio">
                    <audio controls>
                        <source src="@item.SongFilePath" id="@item.Id" type="audio/mp3" />
                    </audio>
                </article>
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.HeaderId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.SongId)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.DateAdded)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
                @Html.ActionLink("Details", "Details", new { id = item.Id }) |
                @Html.ActionLink("Delete", "Delete", new { id = item.Id })
            </td>
        </tr>
    }

</table>

these codes are my controller:

public ActionResult Index()
    {
        List<Playlist_Contents_MVC> model = new List<Playlist_Contents_MVC>();
        model.Add(new Playlist_Contents_MVC() { DateAdded = DateTime.Now, HeaderId = 1, Id = 1, SongId = 1, SongFilePath = "/mp3FolderOnServer/1.mp3" });
        model.Add(new Playlist_Contents_MVC() { DateAdded = DateTime.Now, HeaderId = 2, Id = 2, SongId = 2, SongFilePath = "/mp3FolderOnServer/2.mp3" });
        model.Add(new Playlist_Contents_MVC() { DateAdded = DateTime.Now, HeaderId = 3, Id = 3, SongId = 3, SongFilePath = "/mp3FolderOnServer/3.mp3" });
        model.Add(new Playlist_Contents_MVC() { DateAdded = DateTime.Now, HeaderId = 4, Id = 4, SongId = 4, SongFilePath = "/mp3FolderOnServer/4.mp3" });
        model.Add(new Playlist_Contents_MVC() { DateAdded = DateTime.Now, HeaderId = 5, Id = 5, SongId = 5, SongFilePath = "/mp3FolderOnServer/5.mp3" });
        return View(model);
    }

And finally here is the result:

enter image description here

It is working for me. Please note that I fill my model with sample data. you should fill it with your data from the database. What I believe is that your file path is not correct. Look at my file path which it is from the server location.

Community
  • 1
  • 1
BthGh
  • 192
  • 5
  • Apologies for the confusion, songFile.FILE is just the file path. I should have made it a clearer column name when i made the database table. I tried your changes and it did not seem to work. It seems as though the foreach just skips over the audio tag entirely and looks to render one media player at load time. – Jake Killion Dec 15 '18 at 20:32
  • Thank you very much for giving it a look over :) much appreciated. – Jake Killion Dec 15 '18 at 20:41
  • I have realized that the src attribute does not like the use of the ~ key when referring to a server path, as i have used fine in the past, which was what was causing me to bang my head against the wall for a while with your initial suggestion but after realizing this it works! Thank you so much I am extremely grateful seriously. Have a good one :) @user1825943 – Jake Killion Dec 16 '18 at 21:18
  • Additionally, it did not work initially as i was calling the file using the full path rather than virtual (with the ~ key in the path which caused it to still not work) as an fyi. Thanks again – Jake Killion Dec 16 '18 at 23:12