Pass URL to new View as a parameter - asp.net-mvc

I've spent a couple of hours trying to work out a way to do this. It's such a simple requirement that I can't believe I need to create view models or anything so grandiose.
Very simply, using MVC5, I have a View, let's call it Page1, on which there is a hyperlink. When the user clicks that hyperlink, I want them to be taken to a new View, Page2. On Page2 is an iframe. I want to set the src attribute of that iframe to the URL of Page1, the View that the user was redirected from.
So, if I could maybe use the ViewBag (which people on here don't seem to recommend), to pass the URL of Page1 from that View to the Controller for Page2, and then use Razor in my markup on Page2 to define the src attribute of the iframe, I imagine that'd work fine. Unfortunately, people don't seem to like using ViewBag, and also, I can't find an end-to-end description of how to actually achieve this in code.
Can somebody give me an appropriately straightforward solution to this problem?

A ViewModel for a View can simply be a string - so if you only need to pass a single value in to the view (the URL to use as the src), then in Page2.cshtml, you just define the model at the top like so:
#model string
To use that as the src attribute, you just do e.g.
<iframe src="#Model" .... >
And from the controller, you pass the url string as the model to the view like so:
return View("Page2", myUrlStringVariable);
So, to recap, a ViewModel doesn't necessarily have to be a new class you create - for the most basic scenarios like this, you can just use e.g. a string as the ViewModel. As soon as you start having multiple bits of data to pass in to a View, that's typically when you'd look to create a specific ViewModel class.

Another option may be a JavaScript solution. Something like...
document.getElementById('myIframe').src = document.referrer;

Related

ASP MVC3 Pass additional params with "return View(model)"

I'm in serious need of passing url params with View class. Here's code:
if (!ModelState.IsValid)
{
return View(model);
}
This should not only return model based view, but also add specific param to URL (param won't change view details, but is needed as it's one of few automatically generated SessionKeys (one for each tab/window used to view app) and I know no other way to get to it, different than passing as param (it can't be generated everytime, 'cos params will change; it can't be global variable because it'll reset its value each refresh; it can't be static, because static is evul).
Oh this action is called with use of form and submit button, not actionLink or something like this.
EDIT1: I need params to stay in URL after refresh, or I need some other form of keeping data that persists through refresh/validation fail.
If I understand you correctly you have data that you need to use in generating Urls on your page? This just forms part of your ViewModel - or at least it should, since it's data that the View needs in order to render.
You can use ViewData to add any extra data that isn't part of your view model. Or, better still, add the data as members to it. Equally, if different views with different View Models require this data, add a ViewModel base class and derive from that so you can share that data.
use
RedirectToAction("actionName","controller",
new RouteValueDictionary(new {param1="value",param2="value2"});
or you can use hidden field to store the values in your page and then pass this down as and when you need them..

asp.net MVC View page call server side methods

I'd like to know how to call server side methods from a view page. I need a mean to call directly server side methods whatever I need(not just from a model passed from controller)
<img src="#(pictureService.GetPictureUrl(productId)"/> ...
You will need to pass pictureService from a controller via ViewData or via Model, e.g., extend your Model type to contain that property, or use dynamic models add dynamically add such property in controller.
You could possibly also create static class PictureService and call it like you do ni the sample:
<img src="#(MyNamespace.PictureService.GetPictureUrl(productId)"/>
or
#using MyNamespace;
...
<img src="#(PictureService.GetPictureUrl(productId)"/>
What about using en EmptyResult, or a RedirectResult. You don't have to return something, but doing this lets you run a method server side. You could also use a JSON result, and call it using jQuery, then you could return a boolean to say whether it worked or not.
It's hard to tell from your example code, why you don't just serve the image urls with the page. If your image src is known when you serve the page, why not include it in your view model?

Can a controller influence the _layout.cshtml file?

I'm stuck! I'm under the impression that the _layout.cshtml file is used for MasterPage-like content. Everything there is rendered on every page. Naturally, I want to write the code for rendering my sidebar menu in that file.
I want to dynamically display a list of Categories from my DB, but I'm having a problem with passing the actual model of categories to Layout.cshtml since it seems no controller actually touches it.
Any suggestions?
Otherwise please tell me how to approach this problem. I've been wracking my brain for the past three days and still no elegant solution.
I need to:
Dynamically fetch a list of Categories from the DB.
Display this list of Categories on every single view. (Hence the use of _layout.cshtml)
Elegantly handle each different categories click.
I'm at my wits end. :P How would you solve this?
_layout.cshtml
#if(isSectionDefined("Categories"))
{
<div id="sidebar">
#RenderSection("Categories", required: false )
</div>
}
index.cshtml
#section Categories {
<ul>
<li>Category One</li>
<li>Category Two</li>
<li>Category Three</li>
</ul>
}
see this : http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx
Any viewmodel that you pass to your view is automatically available within your master page. If you do not use RenderAction/Action which is the best approach, then you must create the necessary master page data in every action and add it to viewdata - either by having a common base class for your strongly typed viewmodel that contains all master page data or by using the viewdata dictionary.
I would strongly recommend that you go down the html.action approach though. In this way, you have a totally separate controller action for dealing with your list of categories. This action can retrieve the neccesary category data and return the categorylist usercontrol as a partialview and you will not have to worry about polluting all your other actions with this data.
As I see it, ViewData (and its relatives like ViewBag, Model, etc.) is meant for the specific current view. Your _Layout.cshtml is not specific to the current view; and it would be awkward if EVERY controller would have to pass the categories data in addition to whatever else data it needs to pass for the view.
Instead, what I do, is provide a static method in one of my helper classes that retrieves the categories from the DB. I also do some caching there, so that I do not have to hit the DB on every single request. The _Layout.cshtml then simply calls this static method. Simple and elegant.
If you wish, you can bring this out to a partial view, make it a helper method, whatever.
One note of caution though - my custom error view also uses the same _Layout.cshtml, and if the DB goes down, you get an exception trying to display the exception. ASP.NET MVC is smart enough to detect this and abort processing, but you're left with a nondescript default error page. What I did was to place try...catch statements around these dangerous calls, which quietly ignore the exception if the current page is the error view.
I've achieved something similar by having my ViewModels implement an Interface which has members that contain the menu data. In my action method I set that data. Then in my view I check to see if my view-model implements that inteface, pull the menu data out and render the menu (in a partial view actually)

Encapsulating User Controls in ASP.NET MVC

Sorry if this is a basic question - I'm having some trouble making the mental transition to ASP.NET MVC from the page framework.
In the page framework, I often use ASCX files to create small, encapsulated chunks of functionality which get inclded in various places throughout a site. If I'm building a page and I need one of these controls - I just add a reference and everything just works.
As far as I can tell, in MVC, the ASCX file is just a partial view. Does this mean that wherever I want to add one of these units of functionality I also have to add some code to the controller's action method to make sure the relevant ViewData is available to the ASCX?
If this is the case, it seems like a bit of a step backwards to me. It means, for example, that I couldn't just 'drop' a control into a master page without having to add code to every controller whose views use that master page!
I suspect I'm missing something - any help would be appreciated.
Thanks,
- Chris
As far as I can tell, in MVC, the ASCX
file is just a partial view. Does this
mean that wherever I want to add one
of these units of functionality I also
have to add some code to the
controller's action method to make
sure the relevant ViewData is
available to the ASCX?
Yes.
However, you can use a RenderAction method in your view instead of RenderPartial, and all of your functionality (including the data being passed to the sub-view) will be encapsulated.
In other words, this will create a little package that incorporates a controller method, view data, and a partial view, which can be called with one line of code from within your main view.
Your question has been answered already, but just for sake of completeness, there's another option you might find attractive sometimes.
Have you seen how "controls" are masked on ASP.NET MVC? They are methods of the "HtmlHelper". If you want a textbox bound to "FirstName", for example, you can do:
<%= Html.Textbox("FirstName") %>
And you have things like that for many standard controls.
What you can do is create your own methods like that. To create your own method, you have to create an extension method on the HtmlHelper class, like this:
public static class HtmlHelperExtensions
{
public static string Bold(this HtmlHelper html, string text)
{
return "<b>" + text + "</b>\n";
}
}
Then in your view, after opening the namespace containing this class definition, you can use it like this:
<%= Html.Bold("This text will be in bold-face!") %>
Well, this is not particularly useful. But you can do very interesting things. One I use quite often is a method that takes an enumeration and created a Drop Down List with the values from this enumeration (ex: enum Gender { Male, Female }, and in the view something like Gender: <%= Html.EnumDropDown(Model.Gender) %>).
Good luck!
You can render a partial view and pass a model object to.
<% Html.RenderPartial("MyPartial", ViewData["SomeObject"]);
In your partial view (.ascx) file, you can then use the "Model" object (assuming you've inherited the proper object in your # Control deceleration) to do whatever you need to with that object.
You can, ofcourse, not pass and Model and just take the partial view's text and place it where you want it.
In your main view (.aspx file), you will need to define the proper object in the ViewData that you're passing to the partial view.
Another method you can do is use:
<% Html.RenderAction("MyAction", "MyController", new { Parameter1="Value1"}) %>
What the previous method does is call a controller Action, take its response, and place it where you called the "RenderAction()" method. Its the equivalent of running a request against a controller action and reading the response, except you place the response in another file.
Google "renderaction and renderpartial" for some more information.

ASP.NET MVC - switching the VIew to be used dynamically

What is the correct way to dynamically change the View (the view aspx) that a controller method uses versus using the standard naming convention.
I'm guessing it has something to do with the ViewResult and ViewName, but what is the correct syntax?
Update:
One thing I forgot... is there a way to do this without having the "action" or method name not be part of the resulting URL?
For example,
If I wanted to have a list of all the states in the USA.
http://localhost/list/states
(displays a simple list of state names)
And If I wanted to have a list of the 50 largest cities in the USA.
http://localhost/list/largest-cities
(displays the city and the population - two column grid)
So I'd like to be able to pull in different "formatters" depending on the list name.
Should I do that in a single action / multiple views?
Could I then use Routes to hide the View name in the URL?
What is the best way to approach this?
Just use the method that takes the name of the view to choose. Be careful, though. Most times what you probably want to do is redirect to a different action instead. Returning a different view won't change the url like redirecting will.
string name = ...figure out which view you want...
return View( name );
If you need to render a different view from a controller action dynamically, you can simply supply a value to the base.View() method (or the ViewResult constructor). The location of the view will always be (for the web forms view engine):
/Views/{Controller}/{View}.aspx
Edit: (Thanks to Ithi) It could also be in:
/Views/Shared/{View}.aspx

Resources