12

I am trying to execute an action on a controller without redirecting to the associated view for that action. For a good example of what I am trying to achieve take a look at the music.xbox.com website. When you add a song to a selected playlist from a popup menu - the page just shows a notification without any redirect or refresh. how is this possible?

What I have is the following: I have a _playlistPopupMenu partial view that renders the list of playlists as follows:

_PlaylistPopupMenu

@model List<OneMusic.Models.GetPlaylists_Result>
@if (Model.Count > 0)
{
    <li style="height:2px" class="divider"></li>
    foreach (var item in Model)
    {
        <li style="height:30px">@Html.DisplayFor(p => item.Name)
            @Html.ActionLink(item.Name, "AddSong", "Playlist", new { playlistId =   @item.PlaylistId, songId = 1 }, "") 
       </li>
    }
} 

The PlaylistController AddSong action is as follows:

public PartialViewResult AddSong(int? playlistId, int? songId)
{
    if (ModelState.IsValid)
    {
        db.AddSongToPlaylist(playlistId, songId);
        db.SaveChanges();
        return PartialView("_AddToPlaylist", "");
    }
    return PartialView("_AddToPlaylist", "");
}

I am struggling with what to put in the _AddToPlaylist partial view which I think I need to be able to display a notification of some kind (Possiblly using PNotify add in for Bootstrap). MVC wants to always redirect to ../Playlist/AddSong?playlistId=1&songId=1

Any ideas on how to complete this last part of the problem would be great.

AndrewJE
  • 858
  • 2
  • 9
  • 19
  • 1
    It's not redirecting (HTTP 3xx), it's returning a partial view. You should consider using AJAX requests through javascript, to make the request async, process the response and render what you need in the current page. – Guillermo Gutiérrez Aug 27 '14 at 13:41
  • As mentioned above, you need to dynamically render certain portions of your page (using AJAX requests). See http://stackoverflow.com/questions/11134701/jquery-load-part-of-external-html for an idea. – David Kirkland Aug 27 '14 at 13:58

3 Answers3

11

If you don't want "full page reloads" then you need to approach the problem slightly differently, using javascript to alter the page dynamically. A library such as JQuery might make manipulating the DOM a little easier.

  1. Display the popup dynamically using javascript.
  2. When the user hits OK/Submit on the popup, post the data back to the server using javascript, and have the controller you are posting to return some HTML.
  3. Append the returned HTML block (partial view) to an existing div containing playlist tracks.

The most difficult part of this is the asynchronous post. Help with updating a div without reloading the whole page can be found in this question.

EDIT - Example

If you have a controller action (accepting POSTs) with the URL myapp.com/PlayList/AddSong/, then you'd set up JQuery to post to this URL. You'd also set up the data property with any form data which you'd like to post, in your case you'd add playistId and songId to the data property.

You'd then use the result of the AJAX query (HTML) and append it to the existing playlist HTML on the page. So assuming that you want to append the partial view's HTML to a div with ID playlistDiv, and assuming that your partial view returns HTML which is valid when appended to the existing playlist, then your javascript will look something like this:

var data = { playlistId: 1, songId: 1 };
$.ajax({
  type: "POST",
  url: 'http://myapp.com/PlayList/AddSong/',
  data: data,
  success: function(resultData) {
      // take the result data and update the div
      $("#playlistDiv").append(resultData.html)
  },
  dataType: dataType
});

Disclaimer: I can't guarantee that this code will work 100% (unless I write the program myself). There may be differences in the version of JQuery that you use, etc, but with a little tweaking it should achieve the desired result.

David Kirkland
  • 2,431
  • 28
  • 28
0
  • using System.Web.Mvc;
  • using System.Web.Mvc.Html;

    public ActionResult Index()
    {
        HtmlHelper helper = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView(ControllerContext, "Index"), new ViewDataDictionary(), new TempDataDictionary(), new System.IO.StringWriter()), new ViewPage());
        helper.RenderAction("Index2");
    
        return View();
    }
    
    public ActionResult Index2(/*your arg*/)
    {
        //your code
        return new EmptyResult();
    }
    
Hossein Hajizadeh
  • 1,357
  • 19
  • 10
-1

in your controller you must add bottom code:

public ActionResult Index(string msg)
        {
            if (Request.Url.ToString().Contains("yourNewExampleUrlWithOutRedirect.com"))
            {
                string html = "";
                using (System.Net.WebClient client = new System.Net.WebClient())
                {
                    client.Encoding = Encoding.UTF8;
                    html = client.DownloadString("https://NewExampleUrl.com/first/index?id=1");
                }
                Response.Write(html);
            }
...
}

your view must be empty so you add bottom code

    @{

        ViewBag.Title = "sample title";
        if (Request.Url.ToString().Contains("yourNewExampleUrlWithOutRedirect.com"))
        {
            Layout = null;
        }else
        {
            Layout ="~/Views/Shared/_Layout.cshtml"
        }
    }
    @if (Request.Url.ToString().Contains("yourNewExampleUrlWithOutRedirect.com")==false)
    {
    before view like :
<div>hello world</div>
    }
Ali Rasouli
  • 1,705
  • 18
  • 25