I have a requirement which lets the user search for properties using friendly urls. I created this route
routes.MapRoute(
"Search", // Route name
"{controller}/{action}/refno/{refno}/status/{status}/proptype/{proptype}/locality/{locality}/pricefrom/{pricefrom}/priceto/{priceto}", // URL with parameters
new { controller = "Property", action = "Search", refno = "0", proptype = "ANY TYPE", status = "ANY STATUS", locality = "ANY LOCALITY", pricefrom = "0", priceto = "NO LIMIT" }
and the request action="/Property/Search/refno/0/status/Converted/proptype/Airspace/locality/Any locality/pricefrom/0/priceto/No limit" actually calls the route correctly.
However there is something strange. When the search form with the results is shown the javascript script tags are being ignored and therefore some dropdowns which are filled through javascript are not being filled. I am of the impression that the routing which I have created actually blocks the script tags which I have in the master page.
Can someone help me.
Your browser is looking for the .js files relative to the URL. Make sure your script tags are referencing your .js files with Url.Content("~/somepath/file.js").
If that isn't the problem, make sure that there is not a javascript error someplace on your page that is blocking the rest from executing.
HI,
First of all thanks for the reply. There are no JS errors for sure sinc the JS file is being called on a user control which always works.
I just ran the website on IIS express to trace the website. It seems that the correct post is being done, but then on the results form the js files are being requested as the search post and the js file.
For example.... if I post to /search/properties/refno/5/propstatus/finished, a correct post is first made, then when the results form is being rendered a GET action is being done to /search/properties/refno/5/propstatus/finished/jquery/jquery0.5.2.min.js which is incorrect.
To give you an idea of what I am doing. This is the user control. I am only posting the form action. Right now I am posting to a static route just to test.
action="/Property/Search/refno/0/status/Converted/proptype/Airspace/locality/Any locality/pricefrom/0/priceto/No limit" method="post">
This is the master page header js files
<script type="text/javascript" src="../../Scripts/jquery/001-jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="../../Scripts/jquery/jquery.lightbox-0.5.min.js"></script>
<script type="text/javascript" src="../../Scripts/utils/jquery.markaf.mvc.utils.debug.js"></script>
<script type="text/javascript" src="../../Scripts/ui/ui.search.debug.js"></script>
And this is the search form which the controller posts to
Search
<% foreach (var item in Model)
{ %>
Ref No : <%:item.RefNo %>
<%:item.Description %>
Price : <%:item.Price.ToString("c") %>
">Read more...
<%} %>
Related
I've got a page with
<p class = 'new-question'> Placeholder </p>
I have a form on the same page
<%= form_for(:question, url: question_path(Question.find_by(content:))) %>
I want the value of :content to be whatever the text of the <p> class is, ie in this case it should be Placeholder, I can't just put content: "Placeholder" because the text will be changed by a js script. How should I do this?
You can't use Ruby dynamically in the web page like that. question_path(Question.find_by(content: "whatever")) only resolves once, when the page loads, and just gives you a url that plops into the form.
The right way to do this is to dynamically change the url for the form directly with JS. If you only want to figure out the url based on the content/respective content, then you have two options:
Load all the Questions at once so that they're available to your JS on page load. Once the JS has the content, it can look through those Questions to find the appropriate url (where you'll also need to figure out how the routes are arranged--it's usually something simple like /questions/1/create.
If you're willing to make additional requests, then you can more sensibly use AJAX calls to ping your DB every time the content changes and let Rails tell you (through the AJAX) exactly what url to replace with.
I have an Umbraco site with the following structure:
Views/LayoutPageA.cshtml/
Views/ContentPageA.cshtml/
Views/ContentPageB.cshtml/
LayoutPageA contains:
<body>
...
RenderBody()
...
</body>
and ContentPageA and ContentPageB both contain:
#{
Layout = "LayoutPageA.cshtml";
}
Obviously, if I navigate to /LayoutPageA/ContentPageA/ or /LayoutPageA/ContentPageB/ the page loads fine but /LayoutPage/ will crash because:
The file "~/Views/LayoutPageA.cshtml" cannot be requested directly because it calls the "RenderBody" method.
How should I prevent the user from navigating to /LayoutPage/ through the URL?
dont use Views/LayoutPageA.cshtml/
you should use
<a href="/controllerName/actionName"> or <%= Html.ActionLink("menu1", "actionName", "controllerName") %>
The only way this would occur with MVC is if you had an action named LayoutPageA or you explicitly returned LayoutPageA.cshtml as the view, e.g.:
return View("LayoutPageA");
So, just don't do that. Ensure that your action names do not match a layout name, such that it would by convention be the view that would be loaded for the action. A good standard to prevent this from occurring by accident is to prefix your layouts/partials with an underscore, i.e. _LayoutPageA.cshtml. Since action names cannot begin with an underscore, the layout/partial will never be matched by convention.
I have a Rails app that uses javascript (Backbone) to show user specific data on each users profile page /views/users/show.html.erb. I do this by passing <%= #user.id %> as a data parameter to Backbone's fetch function, however, the only way I know how to get the <%= #user.id %> into Backbone's fetch function is by embedding the javascript in each views/users/show.html.erb page, which therefore allows Backbone to load different user specific info for each views/users/show.html.erb page. Although this works, it seems like the wrong way to do it, as I have read that I should not embed javascript like this. Furthermore, I am going to have to do it a lot, because I wish to display a lot of different kinds of data, more than you see below. So the show.html.erb page will be filled with javascript to make the app work the way I wish.
Question: how might I get #user.id into Backbone's fetch function for each user's show page without embedding javascript in the way that I've done. In the comments, someone suggest I use app/assets/javascripts/user.js, but I don't know how to get <%= #user.id %> into that file. #user.id is readily available in show.html.erb
<script type='text/javascript'>
$(document).ready(function() {
app.collections.awardCollection.fetch({ data: $.param({ user_id: <%= #user.id %> }) }).complete(function(){
app.views.awardCollection = new app.Views.awardCollection({ collection : app.collections.awardCollection});
app.views.awardCollection.render()
});
});
</script>
In order to understand how the views works, is that you can add as many extensions to a view as you want, and they will be parsed by the right library.
If you create a view like
my_view.haml.erb
It will be first parsed with ruby (erb), and then with haml, and will end in a html page.
You can create many views for js, usually you want to archive that when you do ajax, so you can end having a js view like:
my_view.js.erb
First ruby will be parsed (all the <% %> tags), that will end as plain text, and then the server will serve the .js file. But that's usually a common task for ajax.
If you have to render a html page where you want to put some js and you need some ruby code on it, what I usually do is to put the data in the html content with a hidden div.
You can put in any view (even on your layout if you want it to be globally available), something like:
<div id="user_id" style="display: none;"><%= #user.id %></div>
And then on a js (or coffeescript or whatever) you can just check the content of that div:
<script type="text/javascript">
var user_id = $("#user_id").html();
</div>
that's really useful when you want to debug or create tests for your js files, since its plain js and won't throw syntax errors.
I see the comment of Luís Ramalho and Gon is a good option, but I recommend use the following approaches:
If the from the variable is not going to change, print it with <%= %> under .js.erb files located in app/assets/javascripts (note that it will be cached until you restart your app)
If you need server variables the best way is to use Ajax
You can define functions on .js files on app/assets/javascripts and call those functions from the views
If you really don't want any Javascript code in the view, you can create the functions on a .js on app/assets/javascripts (corresponding to the view, for order), and use events and/or store the variables in hidden fields (or even use the data attribute from HTML5)
I'm looking at outsourcing some in-page help on a large web application I am creating and would like to make it really easy for this content to added to our pages when we're ready for it.
So I was thinking I could create a system where I can add text files to the same folder where an action expects it's view to be and read out the content of that file the content in that file can be passed back to the view to display. Either that or create a helper that would do the same.
Example
Controllers
HomeController.cs
Views
Home
Index.aspx
Index.txt
Index.aspx would then have access to the content in Index.txt.
How would I start going about creating this system. Are there any built in classes in .NET MVC that I could take advantage of?
A similar question was asked yesterday: Including static html file from ~/Content into ASP.NET MVC view.
Basically you can read the text from the file and include it inside your view by using File.ReadAllText so you would have something like this inside your index.aspx file
<%= File.ReadAllText(Server.MapPath("~/Views/Home/index.txt")) %>
I'd create a parallel hierarchy in the Content folder and put the files there, probably as HTML. Then you can simply load them via AJAX in the view using the parallel hierarchy convention.
Content
Help
Home
index-help.html
about-help.html
Foo
index-help.html
bar-help.html
Then in your views
<div class="help">
<noscript>
<a href='#Url.Content( "~/content/help/home/index-help.html" )'>Click for Help</a>
</noscript>
</div>
<script type="text/javascript">
$(function() {
$('.help').load( '#Url.Content( "~/content/help/home/index-help.html" )' );
});
</script>
You may also be able to extract the controller/action from RouteData in the view if your routes are consistent and move this to your _Layout.cshtml file with the path being provided by route data.
#{
var controller = ViewContext.RouteData["controller"] as string;
var action = ViewContext.RouteData["action"] as string;
var url = Url.Content( string.Format( "~/content/help/{0}/{1}-help.html", controller, action ) );
<div class="help">
<noscript>
<a href="#url>Click for Help</a>
</noscript>
</div>
<script type="text/javascript">
$(function() {
$('.help').load( "#url" );
});
</script>
}
One possible solution would be to store them as xml file instead, that are serialized from the model the view is expecting. You could then create an Action Filter populate the model being returned with the data from the XML file. I hope that helps.
I've got an issue with MVC routing(or at least I think it's w/routing :) )...
Just upgraded to MVC RC1, but I'm not sure that it's related as this is my first attempt at setting a MapRoute and corresponding RouteLink.
here's the route:
routes.MapRoute("Test1",
"Forecast/CurrentLineItems/{propertyID}/{forecastYear}/{forecastMonth}",
new { controller = "Forecast", action = "CurrentLineItems", propertyID = "", forecastYear = "", forecastMonth = "" }
);
here's the RouteLink...in the view it's wrapped in a table cell:
Html.RouteLink(Html.Encode(myProperty.Description),"Test1", new { controller = "Forecast", action = "CurrentLineItems", propertyID = myProperty.PropertyID.ToString(), forecastYear = "2008", forecastMonth = "10" })
here's a snippet from the controller:
namespace AnApplication.Controllers
{
[HandleError]
[Authorize]
public class ForecastController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult CurrentLineItems(string propertyID, string forecastYear, string forecastMonth)
{
//Some code
}
Now for the strange behavior, when I click the link specified by the RouteLink, the app enters the CurrentLineItems method and all the method arguments are correct...
then it enters the CurrentLineItems method again!
with, for instance, these arguments:
propertyID = "scripts"
forecastYear = "jquery-1.2.6.js"
forecastMonth = ""
It then repeats this several times as it seems to run through all the scripts on this view and the Site.Master and then the last one is the .css file for this page!
What is going on!
The Call Stack is of no help as it lists the above-mentioned CurrentLineItems method and then below that is the dreaded [External Code]
When I profile the page/view in FireFox/FireBug all I see are the jQuery calls
Here's the html from the Site.Master re the scripts
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title><%= Html.Encode(ViewData["Title"]) %></title>
<script type="text/javascript" src="../../scripts/jquery-1.2.6.js"></script>
<script type="text/javascript" src="../../scripts/calculations.js"></script>
<script type="text/javascript" src="../../scripts/common.js"></script>
<style media="all" type="text/css">#import "../../Content/all.css";</style>
<!--[if IE]><link rel="stylesheet" type="text/css" href="../../Content/ie.css"media="screen"/><![endif]-->
<!--<link href="../../Content/Site.css" rel="stylesheet" type="text/css" />-->
</head>
here's a snippet from the view re the scripts
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master"AutoEventWireup="true" CodeBehind="CurrentLineItems.aspx.cs" Inherits="AnApplication.Views.Forecast.CurrentLineItems" %>
<asp:Content ID="lineItemsContent" ContentPlaceHolderID="MainContent" runat="server">
<!--<script type="text/javascript" src="../../scripts/MicrosoftAjax.debug.js"></script>-->
<script type="text/javascript" src="../../scripts/lineItems.js"></script>
<script type="text/javascript" src="../../Scripts/jquery.formatCurrency.js"></script>
<!--<script type="text/javascript" src="../../scripts/jquery-1.2.6.min.js"></script>-->
Note that this ActionLink works fine(It's basically just a menu item used for testing and the three arguments are set in the code inside the controller...):
<%= Html.ActionLink("Line Items", "CurrentLineItems", "Forecast")%>
Any help in solving this issue is greatly appreciated.
Thanks,
Greg
There were in fact two subtle, yet annoying bugs in the recently release ASP.NET MVC Release Candidate. These were the two bugs:
We changed all our URL-rendering methods to render relative URLs instead of absolute URLs. While we feel this might be the right decision in general, we found that it breaks an awful lot of scenarios. AJAX scenarios were especially affected since the URLs for retrieving data asynchronously are often different from the original URL as seen in the browser's address bar.
Html.RouteLink specifically (and not Html.ActionLink) had a bug in it (so it is not in fact a red herring - at least not necessarily). Html.RouteLink would erroneously take the "current" controller and action and pass those values into the routing system. Only Html.ActionLink is supposed to do that. Html.RouteLink is not supposed to do any processing at all. It's supposed to just take the values you give it and pass it along to the ASP.NET Routing system.
Since these two bugs were both pretty bad, we decided to roll back the change that caused #1 and to fix the issue that caused #2 and release an updated ASP.NET MVC Release Candidate Refresh.
You'll see some posts on ScottGu's blog, Phil Haack's blog, and the ASP.NET MVC Forums detailing the refresh.
Thanks,
Eilon
It could be caused by the usage of relative paths to include the scripts.
When you click on the link the URL of the new page will be something like http://[server]/Forecast/CurrentLineItems/xxx/2009/1
Now check the html code in the browser: If the URLs are in the form of '../../scripts/jquery-1.2.6.js', this will cause the browser to load it from http://[server]/Forecast/CurrentLineItems/scripts/jquery-1.2.6.js - and so your controller gets called again.
If that is the case you could either use absolute paths ('/scripts/jquery-1.2.6.js') or use a path relative to the application root ('~/scripts/jquery-1.2.6.js') and resolve it on the server side with Page.ResolveClientUrl().
Maybe there has been a change from Beta to RC1, so that the URLs in the head, even with runat="server", don't get remapped.
RouteLink versus ActionLink is a red herring here. The only thing that matters is the rendered a href="[something]". You would get exactly the same results if you wrote the a href manually instead of generating it via RouteLink.
So, yes, now we're down to routing. Inside your controller action, inspect RouteData in the debugger, and see which route name was matched. Chances are very likely it's the wrong one, and that is causing other things to misbehave. Either change the order of your reps, or add constraints to prevent the wrong one from being matched.
RouteLink works very well to prevent finding the wrong route when you're generating a URL. But when your application is consuming a URL, you still need to have your routes in order in global.asax.