I have an ASP .NET Website where i have an index.aspx page and 3 Folders along with it.ie;My Root has index.aspx ,FolderA,FolderB and then FolderCommon(these 3 are folders).
I have got few asp pages in FolderA and FolderB.FolderCommon stores js files ,CSS files and common code etcc....
I have a user control called pageFooter , inside which i am keeping all footer links of my page.Now my problem is when i use the same footer user control in my index page which is available in the root folder,it will not work for other pages,because the path is different.So how can i redesign the footer user control so that links will be consistent across all pages irrespective of folder structure or the place where they are being present.
Note : I dont want to give a full link to the href property (Ex: http://sitename/folderA/fielname.aspx)
Any thoughts ???
If you are doing asp:Hyperlink, always set the links this way:
NavigateUrl="~/index.aspx"
NavigateURL="~/Folder/Default.aspx"
The ~ basically means "root"
If you are doing regularl <a href=""> then you need to provide the relative path to the link based off wherever the file is.
So if you are in folderA, and you want to reference the root.
We stack with the same problem. We have used absolute URL with following utility to convert already existing '~' to correct path
public static class UrlUtils
{
/// <summary>
///This method returns the correct relative path when installing
/// the portal on a root web site instead of virtual directory
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public static string GetApplicationPath(HttpRequest request)
{
string path = string.Empty;
if (request.ApplicationPath != "/")
path = request.ApplicationPath;
return path;
}
/// <summary>
/// Changes leading '~' to absolute URL including lead address e.g. http[s]://.... using
/// <see cref="HttpContext.Current" />.
/// </summary>
/// <param name="url">Relative or absolute URL.</param>
/// <returns>Absolute URL.</returns>
public static string ResolveAbsoluteUrl(string url)
{
if (url.StartsWith("~"))
{
HttpRequest request = HttpContext.Current.Request;
string _BaseUrl = new Uri(request.Url.ToString()).GetLeftPart(UriPartial.Authority);
string baseUrl;
baseUrl = _BaseUrl + GetApplicationPath(request);
return baseUrl + url.Substring(1);
}
return url;
}
This is (probably) what you have now...
Link
You can try:
Link
And you should find that the slash makes all the difference!
I'm not sure of the exact nature of your problem, but have you tried using root-relative paths? Something like:
"~/Folder/{control or page}"
An example of your code would be helpful.
Could you check the URL of the page the control is on?
Dim currentURL as string = HttpContext.Current.Request.Url.ToString
Once you know the URL you should know which links to show.
Related
I need to port a website to asp.net and decided to use Umbraco as the underlying CMS.
The issue I'm having is I need to retain the URL structure of the current site.
The current URL template looks like the following
domain.com/{brand}/{product}
This is hard to make a route for since it mixes in with all the other content on the site. Like domain.com/foo/bar which is not a brand or product.
I've coded up a IContentFinder, and injected it into the Umbraco pipeline, that check the URL structure and determins if domain.com/{brand} matches any of the known brands on the site, in which case i find the content by its internal route domain.com/products/ and pass along {brand}/{model} as HttpContext Items and return it using the IContentFinder.
This works, but it also means no MVC controller is called. So now I'm left with fetching from the database in the cshtml file which is not so pretty and kind of breaks MVC conventions.
What i really wan't is to take the url domain.com/{brand}/{product} and rewrite it to domain.com/products/{brand}/{product} and then being able to hit a ProductsController serving up the content based on the parameters brand and product.
There are a couple of ways to do this.
It depends a bit on your content setup. If your products exist as pages in Umbraco, then I think you are on the right path.
In your content finder, remember to set the page you've found on the request like this request.PublishedContent = content;
Then you can take advantage of Route Hijacking to add a ProductController that will get called for that request: https://our.umbraco.org/Documentation/Reference/Routing/custom-controllers
Example implementation:
protected bool TryFindContent(PublishedContentRequest docReq, string docType)
{
var segments = docReq.Uri.GetAbsolutePathDecoded().Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
string[] exceptLast = segments.Take(segments.Length - 1).ToArray();
string toMatch = string.Format("/{0}", string.Join("/", exceptLast));
var found = docReq.RoutingContext.UmbracoContext.ContentCache.GetByRoute(toMatch);
if (found != null && found.DocumentTypeAlias == docType)
{
docReq.PublishedContent = found;
return true;
}
return false;
}
public class ProductContentFinder : DoctypeContentFinderBase
{
public override bool TryFindContent(PublishedContentRequest contentRequest)
{
// The "productPage" here is the alias of your documenttype
return TryFindContent(contentRequest, "productPage");
}
}
public class ProductPageController : RenderMvcController {}
In the example the document type has an alias of "productPage". That means that the controller needs to be named exactly "ProductPageController" and inherit the RenderMvcController.
Notice that it does not matter what the actual pages name is.
I am developing Web Application using ASP.NET MVC in C#. But I am having a problem with retrieving full or absolute url. In ASP.NET MVC we get url like this. Url.Content("~/path/to/page"). It will return "path/to/page". But what I want to do is I have a string like this - "~/controller/action".
Let's consider my website domain is www.example.com. If I use Url.Content("~/controller/action"), it will just return "controller/action". I want to get "www.example.com/controller/action". How can I get it?
If you can use the Controller / Action Names...
You should use the Url.Action() method for this.
Typically, Url.Action() will return something similar to what you presently expect when provided with just the Controller and Action names :
// This would yield "Controller/Action"
Url.Action("Action","Controller");
However, when you pass in the protocol parameter (i.e. http, https etc.) then the method will actually return a complete, absolute URL. For the sake of convienence, you can use the Request.Url.Scheme property to access the appropriate protocol as seen below :
// This would yield "http://your-site.com/Controller/Action"
Url.Action("Action", "Controller", null, Request.Url.Scheme);
You can see an example of this in action here.
If you only have a relative URL string...
If you only have access to something like a relative URL (i.e. ~/controller/action), then you may want to create a function that will extend the current functionality of the Url.Content() method to support serving absolute URLs :
public static class UrlExtensions
{
public static string AbsoluteContent(this UrlHelper urlHelper, string contentPath)
{
// Build a URI for the requested path
var url = new Uri(HttpContext.Current.Request.Url, urlHelper.Content(contentPath));
// Return the absolute UrI
return url.AbsoluteUri;
}
}
If defined properly, this would allow you to simply replace your Url.Content() calls with Url.AbsoluteContent() as seen below :
Url.AbsoluteContent("~/Controller/Action")
You can see an example of this approach here.
The following will render a full url, including http or https:
var url = new UrlHelper(System.Web.HttpContext.Current.Request.RequestContext);
var fullUrl = url.Action("YourAction", "YourController", new { id = something }, protocol: System.Web.HttpContext.Current.Request.Url.Scheme);
Output
https://www.yourdomain.com/YourController/YourAction?id=something
I want to create a route that redirects all requests matching certain pattern to a location built using parts of the pattern. I want to grab some segment in the URL and treat the rest like a path to an aspx page in Web Forms application. For example
RouteTable.Routes.MapPageRoute("SomeRouteName", "{something}/{*path}", "~/pages/{*path}/Default.aspx");
Where *path could be something contain "\". The query string should be preserved as a query string.
Is it possible to create souch a route?
I don't know of any way to do it that way.
The more standard way would be to set the target as "~/pages/default.aspx" and then have that page check for the {path} argument and display the corresponding data.
If you really want it in another path, then don't use a {} placeholder. Simply hard code that section of the path (both the source and target).
After looking at several ways to do this I ended up creating my own routing handler that is something like this:
public class SomethingRoutingHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
string something = (string)requestContext.RouteData.Values["something"];
string path = (string)requestContext.RouteData.Values["path"];
string virtualPath = "~/" + path + "Default.aspx";
return BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page)) as Page;
}
}
I then use the RouteData in the pages to access something. I found these articles helpful:
http://msdn.microsoft.com/en-us/magazine/dd347546.aspx
http://www.xdevsoftware.com/blog/post/Default-Route-in-ASPNET-4-URL-Routing.aspx
How would one get resx resource strings into javascript code stored in a .js file?
If your javascript is in a script block in the markup, you can use this syntax:
<%$Resources:Resource, FieldName %>
and it will parse the resource value in as it renders the page... Unfortunately, that will only be parsed if the javascript appears in the body of the page. In an external .js file referenced in a <script> tag, those server tags obviously never get parsed.
I don't want to have to write a ScriptService to return those resources or anything like that, since they don't change after the page is rendered so it's a waste to have something that active.
One possibility could be to write an ashx handler and point the <script> tags to that, but I'm still not sure how I would read in the .js files and parse any server tags like that before streaming the text to the client. Is there a line of code I can run that will do that task similarly to the ASP.NET parser?
Or does anyone have any other suggestions?
Here is my solution for now. I am sure I will need to make it more versatile in the future... but so far this is good.
using System.Collections;
using System.Linq;
using System.Resources;
using System.Web.Mvc;
using System.Web.Script.Serialization;
public class ResourcesController : Controller
{
private static readonly JavaScriptSerializer Serializer = new JavaScriptSerializer();
public ActionResult GetResourcesJavaScript(string resxFileName)
{
var resourceDictionary = new ResXResourceReader(Server.MapPath("~/App_GlobalResources/" + resxFileName + ".resx"))
.Cast<DictionaryEntry>()
.ToDictionary(entry => entry.Key.ToString(), entry => entry.Value.ToString());
var json = Serializer.Serialize(resourceDictionary);
var javaScript = string.Format("window.Resources = window.Resources || {{}}; window.Resources.{0} = {1};", resxFileName, json);
return JavaScript(javaScript);
}
}
// In the RegisterRoutes method in Global.asax:
routes.MapRoute("Resources", "resources/{resxFileName}.js", new { controller = "Resources", action = "GetResourcesJavaScript" });
So I can do
<script src="/resources/Foo.js"></script>
and then my scripts can reference e.g. window.Resources.Foo.Bar and get a string.
There's no native support for this.
I built a JavaScriptResourceHandler a while ago that can serve Serverside resources into the client page via objects where each property on the object represents a localization resource id and its value. You can check this out and download it from this blog post:
http://www.west-wind.com/Weblog/posts/698097.aspx
I've been using this extensively in a number of apps and it works well. The main win on this is that you can localize your resources in one place (Resx or in my case a custom ResourceProvider using a database) rather than having to have multiple localization schemes.
whereas "Common" is the name of the resource file and Msg1 is the fieldname. This also works for culture changes.
Partial Javascript...:
messages:
{
<%=txtRequiredField.UniqueID %>:{
required: "<%=Resources.Common.Msg1 %>",
maxlength: "Only 50 character allowed in required field."
}
}
In a nutshell, make ASP.NET serve javascript rather than HTML for a specific page. Cleanest if done as a custom IHttpHandler, but in a pinch a page will do, just remember to:
1) Clear out all the ASP.NET stuff and make it look like a JS file.
2) Set the content-type to "text/javascript" in the codebehind.
Once you have a script like this setup, you can then create a client-side copy of your resources that other client-side scripts can reference from your app.
If you have your resources in a separate assembly you can use the ResourceSet instead of the filename. Building on #Domenics great answer:
public class ResourcesController : Controller
{
private static readonly JavaScriptSerializer Serializer = new JavaScriptSerializer();
public ActionResult GetResourcesJavaScript()
{
// This avoids the file path dependency.
ResourceSet resourceSet = MyResource.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
// Create dictionary.
var resourceDictionary = resourceSet
.Cast<DictionaryEntry>()
.ToDictionary(entry => entry.Key.ToString(), entry => entry.Value.ToString());
var json = Serializer.Serialize(resourceDictionary);
var javaScript = string.Format("window.Resources = window.Resources || {{}}; window.Resources.resources = {1};", json);
return JavaScript(javaScript);
}
}
The downside is that this will not enable more than one resource-file per action. In that way #Domenics answer is more generic and reusable.
You may also consider using OutputCache, since the resource won't change a lot between requests.
[OutputCache(Duration = 3600, Location = OutputCacheLocation.ServerAndClient)]
public ActionResult GetResourcesJavaScript()
{
// Logic here...
}
http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/improving-performance-with-output-caching-cs
I usually pass the resource string as a parameter to whatever javascript function I'm calling, that way I can continue to use the expression syntax in the HTML.
I the brown field application I'm working on we have an xslt that transforms the resx file into a javascript file as part of the build process. This works well since this is a web application. I'm not sure if the original question is a web application.
use a hidden field to hold the resource string value and then access the field value in javascript
for example :
" />
var todayString= $("input[name=TodayString][type=hidden]").val();
Add the function in the BasePage class:
protected string GetLanguageText(string _key)
{
System.Resources.ResourceManager _resourceTemp = new System.Resources.ResourceManager("Resources.Language", System.Reflection.Assembly.Load("App_GlobalResources"));
return _resourceTemp.GetString(_key);
}
Javascript:
var _resurceValue = "<%=GetLanguageText("UserName")%>";
or direct use:
var _resurceValue = "<%= Resources.Language.UserName %>";
Note:
The Language is my resouce name. Exam: Language.resx and Language.en-US.resx
I just started tinkering with the WCF REST Starter Kit, I watched the screencasts and... I suspect I'm just being stupid. :) Out of the box (with the provided templates) I can create REST services for a singleton resource or a collection of a resource. But what about support for different kinds of resources in the same project? In example if I have Books, I also want to have Authors and Publishers. With the provided templates I don't see an easy way to accomplish this. Creating a service (and thus a VS project) for each resource sounds ridiculous to me. I need to support multiple resource types in a single service so that they can be accessed under a similar URL, so that the user has only to replace the last part, like http://service/books to get all books and http://service/authors/32 to get a particular author.
Can anyone shed some light on this? I know this can be created with a plain WCF service, but the Starter Kit has all the boilerplate in place already, so why not use it? How would one approach a template generated project to add support for different resource types?
Thanks.
I think your overthinking the WCF REST Starter Kit. Try to think of the WCF REST Starter Kit as just a WCF Service that's configured for easy setup in the http environment. The default templates that are setup for the WCF REST Starter Kit are meant to be used as a sample. You will have to just create your own signature or adapt theirs to meet your needs.
The key parts that you'll want to focus on are the code in the .svc file (you can't access it double clicking, you'll have to choose open with) and the [ServiceContract] interfaces.
Modify the [ServiceContract] interface in the code behind provided to look just like it would for a regular WCF Service.
Here is a sample of an ATOM Pub Feed modified for your needs
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceContract]
public partial class LibraryFeed
{
public LibraryFeed()
{
}
/// <summary>
/// Returns an Atom feed.
/// </summary>
/// <returns>Atom feed in response to a HTTP GET request at URLs conforming to the URI template of the WebGetAttribute.</returns>
[WebHelp(Comment = "Gets a list of Books.")]
[WebGet(UriTemplate = "/books/?numItems={numItems}")]
[OperationContract]
public Atom10FeedFormatter GetBooks(int numItems)
{
var books = GetBooks();
List<SyndicationItem> items = GetItems(books, numItems);
SyndicationFeed feed = CreateFeed(items);
WebOperationContext.Current.OutgoingResponse.ContentType = ContentTypes.Atom;
return feed.GetAtom10Formatter();
}
/// <summary>
/// Returns an Atom feed.
/// </summary>
/// <returns>Atom feed in response to a HTTP GET request at URLs conforming to the URI template of the WebGetAttribute.</returns>
[WebHelp(Comment = "Gets a single author.")]
[WebGet(UriTemplate = "/authors/?numItems={numItems}")]
[OperationContract]
public Atom10FeedFormatter GetAuthors(int numItems)
{
var authors = GetAuthors();
List<SyndicationItem> items = GetItems(authors, numItems);
SyndicationFeed feed = CreateFeed(items);
WebOperationContext.Current.OutgoingResponse.ContentType = ContentTypes.Atom;
return feed.GetAtom10Formatter();
}
/// <summary>
/// Returns an Atom feed.
/// </summary>
/// <returns>Atom feed in response to a HTTP GET request at URLs conforming to the URI template of the WebGetAttribute.</returns>
[WebHelp(Comment = "Gets a list of Authors.")]
[WebGet(UriTemplate = "/authors/{id}")]
[OperationContract]
public Atom10FeedFormatter GetAuthor(string id)
{
var author = GetSingleAuthor(id);
WebOperationContext.Current.OutgoingResponse.ContentType = ContentTypes.Atom;
return GetItem(author.GetAtom10Formatter());
}
}