0

i have this model:

public class UsuarioMusica
{
    public int UsuarioMusicaId { get; set; }
    public int UserId { get; set; }
    public int MusicId {get; set;}

}

And i generate a controller and view, but I'll talk only about the create method. My problem is, I need to take the UserId from logged user and "MusicId" to do a relation at table, right? So, I created a search view and search method in music controller, that list all music saved at music model, search view:

@model IEnumerable<TestTcc2.Models.Musica>
@{
    ViewBag.Title = "Search";
    Layout = "~/Views/Shared/_LayoutOuvinte.cshtml";
}
<h2>Busca de Música</h2>
<table class="table table-hover table-bordered">
       <tr>
        <th>
            <span>Genero</span>
        </th>

        <th>
            <span>Nome</span>
        </th>
        <th>
            <span>Artista</span>
        </th>
        <th>
            <span>Preço</span>
        </th>
        <th></th>
    </tr>
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.genero.Nome)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Nome)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.NomeArtista)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Preco)
        </td>
        <td>
            @Html.ActionLink("Play", "", new { path = item.path }) |
        </td>
    </tr>
}
</table>

My Idea is, in this view, I'll create a new link for each row like @Html.ActionLink("Add music to my collection", "Create", "UsuarioMusica" }) that will call the create method and will add to usuarioMusica model the userId from logged user and musicId from music listed at table.

But I don't have idea how to do this on create method at UsuarioMusica controller, actually, this is my create method:

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(UsuarioMusica usuariomusica)
        {
            if (ModelState.IsValid)
            {
                db.UsuarioMusicas.Add(usuariomusica);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(usuariomusica);
        }

The principal dificulty here, is how to modify the create method to take the userID, musicID from music in row that user create on link "Add music to my collection" and save at UsuarioMusica table.

7
  • Your view does not even show any <form> elements for posting back to the Create() method, and since you already know the UserId in the controller, the method probably just needs to have parameter int musicID. You should also consider using ajax for this so the user stays on the same page and can continue to add new music items to their collection without constantly redirecting back to the same view. Commented Mar 11, 2015 at 0:26
  • @StephenMuecke I can put a <form> in search view and UserId is not a problem, i know how to take it, my problem is, if I put the @Html.ActionLink("Add music to my collection", "Create", "UsuarioMusica" }) in the search view, I'll get a error, because i have two models on the same view. Commented Mar 11, 2015 at 0:31
  • @StephenMuecke First I need to resolve this, and before, i need to resolve how I'll modify the create method to add on database Commented Mar 11, 2015 at 0:32
  • Why do you have 2 models on the same view? It can be @Html.ActionLink("Add music to my collection", "Create", "UsuarioMusica", new { id = item.ID }) to pass the ID to the create method, but ActionLink is a GET, not a POST. You need a <form> element and add a route value for the item.ID so its a POST, but I recommend you use ajax for this. Commented Mar 11, 2015 at 0:36
  • @StephenMuecke Because on first line of view I call a model @model IEnumerable<TestTcc2.Models.Musica> and on actionLink i'm calling another model UsuarioMusica, understand? I never use Ajax, do you have any example to send me? Commented Mar 11, 2015 at 0:41

1 Answer 1

2

@Html.ActionLink is a redirect to a GET method. You would need to include a <form> element for each row that posts the items ID. However this would mean recreating the view each time you post, so you will greatly improve performance using ajax.

@foreach (var item in Model) {
  <tr>
    <td>
      @Html.DisplayFor(m => item.genero.Nome)
    </td>
    ......
    <td>
      <button type="button" class="addmusic" data-id="@item.MusicaId">Add</button>
    </td>
}

Note the items ID is added to the buttons data attributes so it can be retrieved in the script

Script

var url = '@Url.Action("Create", "YourControllerName")'; // adjust to suit
$('.addmusic').click(function() {
  var self = $(this);
  // Get the ID
  var id = self.data('id');
  // post the value
  $.post(url, { musicaID: id }, function(data) {
    if(data) {
      // remove the button so the item cannot be added more than once
      self.remove();
    } else {
      // Oops, something went wrong - display message?
    }
  });
});

Note: to remove the items row from the DOM (not just the button), use

if(data) {
  var row = self.closest('tr')
  row.remove();
}

And the controller

[HttpPost]
public JsonResult Create(int musicaID)
{
  var userID = // you should know this on the server
  // call a service that saves the userID and musicaID to the database
  var usuariomusica = new UsuarioMusica()
  {
    UserId = userID,
    MusicId = musicaID
  };
  db.UsuarioMusicas.Add(usuariomusica);
  db.SaveChanges();
  return Json(true);
}

Note: If the save method fails, then use return Json(null) so the script is informed there was a failure. Note also the absence of [ValidateAntiForgeryToken]. If you want this, then the token also need to be passed in the ajax request as follows

var token = $('input[name="__RequestVerificationToken"]').val();
$.post(url, { musicaID: id, __RequestVerificationToken: token }, function(data) {
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks Stephen, I'm trying to implement the ajax script, but i'm getting a syntax error on the last } i'm trying to resolve, don't care about this, you're already helping me a lot
I have just cut and paste the script from the second code snippet above into a view and there are no 'syntax' errors, so not sure what you may have done wrong
I don't have a service that saves the userId/MusicaID in database, if you look on my question, i put my create method, and in row db.UsuarioMusicas.Add(usuariomusica); the method will add the usuariomusica in database, i'll need to create another method to pass the variables musicaID and userID to add in database
UsuarioMusica is a class that contains properties UserId and MusicId, so just initialize and new instance of UsuarioMusica, set the properties and save it using the Add method - var x = new UsuarioMusica() { UserId = userID, MusicId = musicaID }; db.UsuarioMusicas.Add(x);
Thank you @Stephen, it's working now, I only need to adjust the layout of table and implement the function to remove the line when user click on add button

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.