how to open multiple windows from the controller in asp.net MVC - asp.net-mvc-4

How to open multiple windows from the controller?
For example, I have a controller that gets all the clients and for each client I want that his info is displayed in a different window or tab.
Is that possible using asp.net MVC 4?

I've done this exact thing, it was based on a button click which would fire multiple windows based on the parameters. Here's what you could do. Your controller would be like this...
[HttpPost]
public ActionResult CopyOpportunitySave(CopyOpportunityViewModel model)
{
ViewModel model = new ViewModel();
foreach (var url in "List object that contains URLS")
{
model.ClientURLs.Add(url);
}
return View("CopyOpportunity", model);
}
So now your Model class will have a property like
public List<string> ClientURLs{get; set;}
which is populated by all the URLs you will need to do a window.Open.
and Now in your view you can say
#foreach (var u in ViewModel.ClientURLs)
{
<script>
window.open(u);
</script>
}
just as long as the script inside the foreach loop is getting executed, it will work

This won't be possible by just using native MVC 4. However, one could think of some work-arounds which might resemble your requirements. For starters, is it necessary to actually open a 'browser tab' per client, or could this also be a tab page per client in one single HTML-document. If the latter is an option, you could take a look at different 'tab' controls being available in HTML.
If your really want a new browser window per client, my hint would be to return the list of possible clients to one HTML page and then use scripting in that HTML page to open a popup window for each client. For each popup / client an additional request needs to be send to the server.

Just make the link (<a></a>) that opens the client information have a target = "_blank":
John Smith
If you are using Html helpers it could be like this:
#Html.ActionLink("John Smith", "Details", "Clients", new {id = 1}, new { target = "_blank"})
This will open a new browser tab with the page you need.

Related

Get SelectedItem in Dropdownlist without FormMethod.Post

I have a dropdownlist that is bound to a list in my model. Model.list_IDs
The current page is an "editing" page where a user would inherently change a property of the model by using the dropdownlist.
#Html.DropDownListFor(model => Model.ID, Model.list_IDs, new { style = "width:250px" })
The items within the dropdownlist are not intuitive, so I would like to provide a button, that when clicked, retrieves additional information via a stored procedure (called from the controller via a method called GetDetails)
The button is created through an action link, and I plan to display a partial view (like a focused pop up window) that shows the additional information once the button is clicked.
#Html.ActionLink(" ", "GetDetails", new { id = Model.ID.ToString() }, new { #class = "lnkMagnify16", title = "View Details" })
Obviously Model.ID.ToString() is incorrect, because it will only send the model's current ID, rather than the ID currently selected in the dropdownlist.
How can I change Model.ID.ToString() to represent the dropdownlist's current selected item?
I know there is a way to do this using FormMethod.Post (Get selected item in DropDownList ASP.NET MVC) but I do not want to reload the page with a submit button. I'd also like to avoid "third party" approaches like JavaScript if possible.
JavaScript is not a "third party" approach, and it's also the only way to accomplish what you want here. Whether by a standard form post or via AJAX (JavaScript), you must make a new request to the server to get the new information you want.
Now, since all you're specifically after is a way to dynamically update the the Model.ID value in the link, you can do that without AJAX or a form post, but you still must use JavaScript, since all dynamic behavior client-side originates from JavaScript. Basically, you'd need to bind to the change event of the dropdown and alter the href property of your link.
document.getElementById('ID').addEventListener('change', function () {
var selectedId = this.options[this.selectedIndex].value;
document.getElementById('AwesomeLink').href = // alter `href` with `selectedId`
});
However, that link is still going to change the whole view if the user clicks it. If you truly want the user to stay on the page, then you'll need to fetch the response of that link using AJAX and then either add it to the page somehow, whether that be directly or via a modal popup (which will required yet even further JavaScript to achieve). Also, it's not clear how the Model.ID value ends up in the URL, i.e. whether it's part of the path (/some/url/{id}/) or as a query string param (/some/url/?id={id}). If it's the former, I'd recommend switching to the latter, as it will make it much easier to build your URL client-side.
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", function (response) {
// add response.responseText to the DOM
});
xhr.open("GET", "/some/url/?id=" + selectedId);
xhr.send();

Web browser control, modal window/popup to STAY INSIDE web browser control for Visual Studio 2015/Visual Basic 2015

this is the first time I'm posting a question here; I have searched and searched and searched here and other places and I cannot seem to get any results. I'm using VISUAL BASIC 2015 in Visual Studio 2015. QUESTION: I need to have a modal window/popup from a particular website remain INSIDE the web browser control/window on my form (WebBrowser1); when a particular link is clicked, the modal window/popup jumps out of the form and directly to the user on their screen. I have to keep this popup inside because there are other links to be clicked on that popup, but if it jumps out of the web browser control, no code will work since it's outside WebBrowser1. What I have found is code for older versions, and not 2015; if anything I can even add WebBrowser2 to have the popups/modal windows appear there if possible, just as long as I can code them to keep clicking inside the form. PLEASE HELP! THANK YOU!
window.open (and a click on <a target="_blank"> etc) can be handled via the NewWindow2 event. Hans already pointed out how to do that in comments. NewWindow3 works too, but need at least Windows XP SP2.
As for window.showModalDialog, it is a bit tricky. IE has IDispatchEx (wrapped as IExpando in .Net) implemented on scripting objects so you replace the methods and properties with your own implementation. But window.showModalDialog shows a dialog that has arguments and return values, you need to override those properties in the modal dialog you create too. The code looks roughly like tis:
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//skip events from frames
if(WebBrowserReadyState.Complete!=webBrowser1.ReadyState) return;
if(FindLoginFormOnPage()) {DoLogin();return;}
if(IsWelcomePage()){NavigateToPage1();return;}
if(IsPage1()){SubmitFormOnPage1();return;}
if(IsPage1FormResult()){
var document=webBrowser1.Document.DomDocument as mshtml.ITMLDocument2;
var expando =(IExpando)document.parentWindow;
expando.RemoveMember(expando.GetMethod("showModalDialog"
,BindingFlags.Instance | BindingFlags.Public);
expando.AddMethod("showModalDialog"
,new ShowModalDialogDelegate(this.MyShowModalDialog));
}
......
}
object MyShowModalDialog(string url, object varArgIn, object options)
{
using(FromMyShowModalDialog myShowModalDialog
=new MyShowModalDialog())
{
myShowModalDialog.StartupUrl=url;
myShowModalDialog.DialogArguments=varArgIn;
//omit the code to parse options
//and set dialog height/width/topleft location etc
if(myShowModalDialog.ShowDialog()==DialogResult.OK)
{
//do something on the return value before passing to the scripts
......
return myShowModalDialog.ReturnValue;
}
return null;
}
}
and in the Load event handler of MyShowModalDialog you call something like webBrowser1.Navigate to show the page requested by the parent page.
Now you need to pass the arguments to the webbrowser control on the new form. Do the same as above but replace another property this time.
expando.RemoveProperty("dialogArguments");
expando.AddProperty("dialogArguments")
.SetValue(expando,this.DialogArguments);
This will let the web page access the value passed from MyShowModalDialog and stored in this.DialogArguments.
The earliest you can access the DOM is in webBrowser1_DocumentCompleted. By that time the scipts on the page that read window.dialogArguments are probably already executed and got nothing. After overriding window.dialogArguments, you need to study the script on the page to find out how to revert that. for example, if the page has
<head>
<script>
var oMyObject = window.dialogArguments;
var sFirstName = oMyObject.firstName;
var sLastName = oMyObject.lastName;
</script>
...
<span style="color: 00ff7f">
<script>
document.write(sFirstName);
</script>
</span>
you need to change the values of sFirstName and sLastName then change the innerText property of the span, probably identify via its relationship with a named div or table cell. You can write the necessary changes in a script and call it via HtmlDocument.InvokeScript.
If the page returns a value to its parent, you need to pass it on to your parent form too. Override window.returnValue so when the script writes to window.returnValue it writes to a variable you provided
......
expando.RemoveProperty("returnValue");
expando.AddProperty("returnValue").SetValue(expando,this.ReturnValue);

MVC 4.0 using Razor view

How to set the Label Text which is available on _Layout.cstml from different Controller.
For Example
If I want to navigate from Dashboard to ProductList Page. Then My Label Text on _Layout Page should be "Product List". which I am setting from ProductList Controller Index Method.
Thanks in advance.
Use the ViewBag.xyz in _Layout.cshtml. Pass the viewdata from controller action and it will be shown on your html page.
Note:- Please confirm me if you means something else. I will update my answer if this doesn't means what you looking for.
it's look like you want to set the ViewBag.Xyz different different for every controller.
I recommanded you to use ActionFilterAttribute to make it work. The code will something like this.
public class DashboardCustomData : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Controller.ViewBag.xyz = "This is my Dashboard page";
base.OnActionExecuting(filterContext);
}
}
Now put this Actionfilter to every controller. You need to use different different ActionFilter for every controller which have different title. After doing this you never need to set it manually from every controller.
If you don't like to write the multiple filter then try this one.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
string controllerName = filterContext.RouteData.Values["Controller"].ToString();
string ActionName = filterContext.RouteData.Values["Action"].ToString();
if (controllerName == "Dashboard")
{
filterContext.Controller.ViewBag.xyz = "This is my Dashboard page";
}
else
{
}
base.OnActionExecuting(filterContext);
}
You make BaseViewModel class with that prop, set _Layout's model as this type and derive other models from it. Now you can access that prop from any derived model
You use ViewBag or ViewData
You make a #section in Layout view and populate it within Controller's views
If you need Layout's fields in many controllers then usage of #1 looks preferred.
Why does not use this simple approach:
#{
ViewBag.Name = "...";
Layout = "_Layout.cstml";
}
And in your layout set your lable text with #ViewBag.Name
Layout
<label>#ViewBag.Label</label>
Then just assign a value to ViewBag.Label in your controllers, and it will automatically change.
public ActionResult OtherPage()
{
ViewBag.Label = "Other Label";
}
Solution you have suggested works when I am on the same Controllers View but here I want to Change the Text of Controller on Master Page.
In Asp.net We use Master Page Reference on Child Page then we can
easily Change the Text, but how do i do same in MVC... Hope you
understood the scenario. –
If you look at what is generated when you start a new project with the "Internet Template" in MVC 4, you have a way to do it already working for you:
In the element of _Layout, look for <title>#ViewBag.Title - My ASP.NET MVC Application</title>, then in all the different views, you have something like this:
#{
ViewBag.Title = "Contact";
}
<hgroup class="title">
<h1>#ViewBag.Title.</h1>
<h2>#ViewBag.Message</h2>
</hgroup>
All you need to do is to move/duplicate ViewBag.Title out of the HEAD intot the BODY, or create your own ViewBag variable, and set it's values from your different views. Obviously you could just as well set the value from the controller, but I don't see the need, as this really has to do exclusively with the user interface, which is the Views job.
Finally, if I may, don't try to duplicate in MVC what you're used to with ASP.NET. The paradigms are way too differents, chances are that you are going to waste time while there might be an easy MVC way to achieve the same thing.
It seems to me this is just an example of it.....

Windows 8 app: How to pass a parameter on GoBack()?

There are a lot of samples showing how to pass a parameter on navigating to a page in Window 8 (WinRT). But I could not find any hint for passing parameters going back.
Situation: The user navigates to a details page of same data. The data is passed to the page by
Frame.Navigate(typeof(DedtailsPage), data);
How can I pass back the changed data on GoBack()?
Store the reference to data somewhere and retrieve it when you navigate back?
Also note that it's best not to pass objects other than simple strings or values between pages, since only simple types are supported for storing frame navigation state in case your app gets suspended.
I know, that this is a very bad idea, but usualy I use this:
To write:
Frame rootFrame = Window.Current.Content as Frame;
rootFrame.Tag = myObject1;
To read:
Frame rootFrame = Window.Current.Content as Frame;
var myObject2 = rootFrame.Tag;
I've made another choice to handle this.
Keep in mind that I'm a Xamarin developer (not Forms!) so i was looking for a solution which was similar for all platforms: iOS, Android and Windows.
I am a great fun of events, rather than passing objects or storing globals.
So the best choice to pass data from PageB (the child) to PageA (the parent) is to communicate via events.
Some notes: In iOS and Android, when you navigate from a "page" to "page" you can do this by passing an instance of the target object you want to navigate to. In iOS you create an instance of a custom UIViewController. In Android you create an instance of a custom Fragment. Doing this allow you to attach events handler to your instances.
An example:
var controller = new ExtrasViewController();
controller.ExtraSelected += ExtrasFragment_ExtraSelected;
controller.ExtrasCleared += ExtrasFragment_ExtrasCleared;
this.NavigationController.PushViewController(controller, false);
In WinRT Apps you are only allowed to pass "types" of target page to navigate to. So the only way to attach event handlers to your page instance is to use the OnNavigatedFrom method from the calling page. So suppose you are in PageA and want to attach some event handlers to your PageB, before it become active, simply write in your PageA "code behind":
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
var page = e.Content as ExtraBody;
if(page != null)
{
page.ExtraSelected += ExtrasFragment_ExtraSelected;
page.ExtrasCleared += ExtrasFragment_ExtrasCleared;
}
}

Reusing Views and Viewmodel with MEF & Silverlight

Here is what I'd like to do :
I have an Silverlight application using navigation frame and MEF. (like this one : http://msdn.microsoft.com/en-us/magazine/gg535672.aspx)
This application consists of a set of buttons. Each button click load a view and its associated ViewModel.
Within theses views, I've a list with items and when I click on each items it refreshs a kind of sub-view in this view.
I'd like to create a navigation system : for example myapp.aspx#view1/2, where 2 is in fact the item clicked in the list. If I click on one of the button, it would load a default item and refresh all the view, but when I click on an item, I wouldn't like to refresh all the view but only certain part of the view (I do not want to create another instance of the view and viewmodel).
My problem is in fact that I would like to get the best pratice to get a reference to an existing view or viewmodel when i'm navigating to this page that has already been loaded (for example from myapp.aspx#view1/2 to myapp.aspx#view1/3)(I plan to do this into the BeginLoad of the ContentLoader class)
If I get the viewmodel, I can do that I want by changing for example the current itemId property which could refresh the view thanks to binding.
Thanks in davance if you have something to propose.
A common approach is to use some form of Messenger to do this type of operation. The item's click could trigger the sending of a message, with the Item attached. The ViewModel in question would be a subscriber, and edit its current settings (ie: it's ItemId, which would trigger the binding refresh).
The most common implementations are usually ones similar to the Messenger service in MVVM Light.
It's fairly easy to roll your own here, though, especially since you're already using MEF. Just create a service to handle the message passing, and import it into both endpoints.
Actually, I would have prefered to use an URI to navigate in my application when I click on an item, but if I use an URI, the entire view is reloading and not the specific part I'd like to.
With the messenger, I won't be able to use navigation with url within the view, I think ? Or else I didn't really figure out what you proposed to me.
The algorithm I would like to take is :
navigate("...asp#MyView1/1")
MyView1 is current view ?
yes then I'd like to get the viewmodel of the current view and change it the ItemId property with 1
no, then the view will be created
And I'd like to implement this algorithm there : (this is the place where the view is instancied for each navigation, in my CompositionNavigationContentLoader class)
public IAsyncResult BeginLoad(Uri targetUri, Uri currentUri, AsyncCallback userCallback, object asyncState)
{
// Convert to a dummy relative Uri so we can access the host.
var relativeUri = new Uri("http://" + targetUri.OriginalString, UriKind.Absolute);
// Get the factory for the ViewModel.
var viewModelMapping = ViewModelExports.FirstOrDefault(o => o.Metadata.Key.Equals(relativeUri.Host, StringComparison.OrdinalIgnoreCase));
if (viewModelMapping == null)
throw new InvalidOperationException(
String.Format("Unable to navigate to: {0}. Could not locate the ViewModel.", targetUri.OriginalString));
// Get the factory for the View.
var viewMapping = ViewExports.FirstOrDefault(o => o.Metadata.ViewModelContract == viewModelMapping.Metadata.ViewModelContract);
if (viewMapping == null)
throw new InvalidOperationException(
String.Format("Unable to navigate to: {0}. Could not locate the View.", targetUri.OriginalString));
// Resolve both the View and the ViewModel.
var viewFactory = viewMapping.CreateExport();
var view = viewFactory.Value as Control;
var viewModelFactory = viewModelMapping.CreateExport();
var viewModel = viewModelFactory.Value as IViewModel;
// Attach ViewModel to View.
view.DataContext = viewModel;
viewModel.OnLoaded();
Thanks.