63

Is there any way to open a view from a controller action in a new window?

public ActionResult NewWindow()
{
    // some code
    return View();
}

How would I get the NewWindow.cshtml view to open in a new browser tab?

I know how to do it from a link in the view - that is not the question. Has anyone figured out a way to do it from the controller action?

alex
  • 6,818
  • 9
  • 52
  • 103
Joe
  • 4,143
  • 8
  • 37
  • 65

8 Answers8

88

This cannot be done from within the controller itself, but rather from your View. As I see it, you have two options:

  1. Decorate your link with the "_blank" attribute (examples using HTML helper and straight HMTL syntax)

    • @Html.ActionLink("linkText", "Action", new {controller="Controller"}, new {target="_blank"})
    • <a href="@Url.Action("Action", "Controller")" target="_blank">Link Text</a>
  2. Use Javascript to open a new window

    window.open("Link URL")

Tommy
  • 39,592
  • 10
  • 90
  • 121
  • 1
    I use this if I want to open a view in a new window from the link: @Html.ActionLink("linkText", "Action", "Controller", new { target="_blank" }. Haven't tested passing the controller as an object routeValue, why would you? But that was not the question. You did answer the origianl question though with "cannot be done" so I'll mark this as the answer. – Joe Feb 13 '13 at 17:12
  • 1
    @Joe - That is just the choice in Html.ActionLink overloads that I use which is of the following signature - Html.ActionLink(string linkText, string Action, object routeValues, object htmlAttributes) - but its just a personal choice and you can use any overload you wish that accepts the htmlAttributes parameter. – Tommy Feb 13 '13 at 17:34
  • Is there a way to define dimensions for the new window? (using razor) – phougatv May 31 '16 at 13:24
  • 1
    @barnes - the only method I know of how to ask the popup to be a certain size is through javascript. Reason: Most any other time, the browser determines what to do with the window. JavaScript is the only part of your entire web app stack that can actually manipulate the client browser. – Tommy May 31 '16 at 13:27
  • 1
    Is this what you are referring to [LINK](http://stackoverflow.com/questions/21731653/mvc-button-should-open-url-in-new-window-tab/#answer-21752757). Do share if you know a better way. – phougatv May 31 '16 at 13:31
  • @barnes - You got it man - that's the only way I am aware of. – Tommy May 31 '16 at 18:30
  • But how one post the form object with this? – AKS Jul 05 '16 at 10:23
  • What if Action Method returns PartialView? Because Partial View is not gonna have Parent View in new window? How to manage that scenario? – Faizan Mubasher Sep 07 '16 at 14:20
46

You can use Tommy's method in forms as well:

@using (Html.BeginForm("Action", "Controller", FormMethod.Get, new { target = "_blank" }))
{
//code
}
Jeff Beck
  • 558
  • 5
  • 10
  • Out of all the possible solutions I have found, this is the best , in my opnion. It is the simplest since it uses the MVC framework. – mcampos Feb 22 '16 at 16:43
  • The default submit action is to post and submit for final action. How can we post the form yet to launch the partial view (so in separate window) to avoid main window data loss. Simple scenario is like main form submit is submit the n number of files held at client temporary that user selected and preview the first. but user may have a preview a certain file while still not submit the form. in that case user may need to view that file in new tab. so how can we have two POST methods for a form with a different view. – AKS Jul 05 '16 at 10:30
  • This works well if you know the request should ALWAYS open in a new window (only). If you might be detecting errors on the server side in the action method (typ. a POST action), then you do not want the returned view to be in a new tab ... you want to use "return View(model)" with errors added to the ModelState instead. Be careful with new windows if using a POST request type for your form... – IdahoB Nov 15 '17 at 20:22
  • AKS - Use a single POST but add an identifier to your model so that your post back action can detect what you intended to do, e.g. a SelectedAction enum (or bool or ....). It's good practice to marry GET and POST action methods, even if the post back might itself redirect to some other action. – IdahoB Nov 15 '17 at 20:25
8

You're asking the wrong question. The codebehind (controller) has nothing to do with what the frontend does. In fact, that's the strength of MVC -- you separate the code/concept from the view.

If you want an action to open in a new window, then links to that action need to tell the browser to open a new window when clicked.

A pseudo example: <a href="NewWindow" target="_new">Click Me</a>

And that's all there is to it. Set the target of links to that action.

Eli Gassert
  • 9,745
  • 3
  • 30
  • 39
  • What is view code for the POST controller method like with the submit action from view passing form object etc. ? The above make the action by default GET. – AKS Jul 05 '16 at 10:58
  • If you had to do it with a post, then you would make a `
    ` Again, that's a front-end solution and has nothing to do with backend.
    – Eli Gassert Jul 05 '16 at 15:33
4

Yeah you can do some tricky works to simulate what you want:

1) Call your controller from a view by ajax. 2) Return your View

3) Use something like the following in the success (or maybe error! error works for me!) section of your $.ajax request:

$("#imgPrint").click(function () {
        $.ajax({
            url: ...,
            type: 'POST', dataType: 'json',
            data: $("#frm").serialize(),
            success: function (data, textStatus, jqXHR) {
                //Here it is:
                //Gets the model state
                var isValid = '@Html.Raw(Json.Encode(ViewData.ModelState.IsValid))'; 
                // checks that model is valid                    
                if (isValid == 'true') {
                    //open new tab or window - according to configs of browser
                    var w = window.open();
                    //put what controller gave in the new tab or win 
                    $(w.document.body).html(jqXHR.responseText);
                }
                $("#imgSpinner1").hide();
            },
            error: function (jqXHR, textStatus, errorThrown) {
                // And here it is for error section. 
                //Pay attention to different order of 
                //parameters of success and error sections!
                var isValid = '@Html.Raw(Json.Encode(ViewData.ModelState.IsValid))';                    
                if (isValid == 'true') {
                    var w = window.open();
                    $(w.document.body).html(jqXHR.responseText);
                }
                $("#imgSpinner1").hide();
            },
            beforeSend: function () { $("#imgSpinner1").show(); },
            complete: function () { $("#imgSpinner1").hide(); }
        });            
    });      
Amin Saqi
  • 18,549
  • 7
  • 50
  • 70
2

You can use as follows

public ActionResult NewWindow()
{
    return Content("<script>window.open('{url}','_blank')</script>");
}
cemahi
  • 27
  • 5
0
@Html.ActionLink("linkText", "Action", new {controller="Controller"}, new {target="_blank",@class="edit"})

   script below will open the action view url in a new window

<script type="text/javascript">
    $(function (){
        $('a.edit').click(function () {
            var url = $(this).attr('href');
            window.open(url, "popupWindow", "width=600,height=800,scrollbars=yes");
            });
            return false;
        });   
</script>
0

I've seen where you can do something like this, assuming "NewWindow.cshtml" is in your "Home" folder:

string url = "/Home/NewWindow";
return JavaScript(string.Format("window.open('{0}', '_blank', 'left=100,top=100,width=500,height=500,toolbar=no,resizable=no,scrollable=yes');", url));

or

return Content("/Home/NewWindow");

If you just want to open views in tabs, you could use JavaScript click events to render your partial views. This would be your controller method for NewWindow.cshtml:

public ActionResult DisplayNewWindow(NewWindowModel nwm) {
    // build model list based on its properties & values
    nwm.Name = "John Doe";
    nwm.Address = "123 Main Street";
    return PartialView("NewWindow", nwm);
}

Your markup on your page this is calling it would go like this:

<input type="button" id="btnNewWin" value="Open Window" />
<div id="newWinResults" />

And the JavaScript (requires jQuery):

var url = '@Url.Action("NewWindow", "Home")';
$('btnNewWin').on('click', function() {
    var model = "{ 'Name': 'Jane Doe', 'Address': '555 Main Street' }"; // you must build your JSON you intend to pass into the "NewWindowModel" manually
    $('#newWinResults').load(url, model); // may need to do JSON.stringify(model)
});

Note that this JSON would overwrite what is in that C# function above. I had it there for demonstration purposes on how you could hard-code values, only.

(Adapted from Rendering partial view on button click in ASP.NET MVC)

vapcguy
  • 7,097
  • 1
  • 56
  • 52
0

I assigned the javascript in my Controller:

model.linkCode = "window.open('https://www.yahoo.com', '_blank')";

And in my view:

@section Scripts{
    <script @Html.CspScriptNonce()>

    $(function () {

        @if (!String.IsNullOrEmpty(Model.linkCode))
        {
            WriteLiteral(Model.linkCode);
        }
    });

That opened a new tab with the link, and went to it.

Interestingly, run locally it engaged a popup blocker, but seemed to work fine on the servers.