Calling node.NiceUrl gives me # in Umbraco - c#

Doing a project in Umbraco, and i've encountered problems in one case that when calling node.NiceUrl I get # as the result. What is weird though is that if i debug it somehow it resolves into the correct url.
var pages = Pages.Select((item, index) => new
{
Url = item.NiceUrl,
Selected = item.Id == currentPage.Id,
Index = index
}).ToList();
Where Pages is obtained from:
CurrentPage.Parent.ChildrenAsList

If I do it this way, it works, but I don't know why.
Url = new Node(item.Id).NiceUrl,

I've encountered this error and it was because the id belonged to a media node.
Media is treated differently to other content and there's no easy way of getting the url because different types of media store the url in different ways depending on context. That's why the NiceUrl function doesn't work for media (according to the umbraco developers).
My specific scenario was using images that had been selected using a media picker. I got the url via the following code. I wrapped it up in an extension method so you can consume it from a template in a convenient way.
public static string GetMediaPropertyUrl(this IPublishedContent thisContent, string alias, UmbracoHelper umbracoHelper = null)
{
string url = "";
if (umbracoHelper == null)
umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
var property = thisContent.GetProperty(alias);
string nodeID = property != null ? property.Value.ToString() : "";
if (!string.IsNullOrWhiteSpace(nodeID))
{
//get the media via the umbraco helper
var media = umbracoHelper.TypedMedia(nodeID);
//if we got the media, return the url property
if (media != null)
url = media.Url;
}
return url;
}

Try like this
Url = umbraco.library.NiceUrl(Item.Id);

Related

Setting a Sitecore Item Url by C# to a third party server

In a specific kind of situation, I had to obtain certain data through a RESTful request from a cloud server and then process and present them along the normal Sitecore items. I converted the data from a RESTful request to Sitecore Item through the following code:
private static Item Itemize(HubSpotResult hubSpotResult)
{
Database webDb = Sitecore.Configuration.Factory.GetDatabase("web");
TemplateItem template = webDb.GetItem("/sitecore/templates/User Defined/Pages/HubSpotBlogs");
var id = ID.NewID;
var templateId = template.ID;
var titleFieldId = ID.NewID;
var dateFieldId = ID.NewID;
var navigationTitleFieldId = ID.NewID;
var def = new ItemDefinition(id,"HubSpotBlog", templateId, ID.Null);
var fields = new FieldList();
fields.Add(titleFieldId, "Title");
fields.Add(dateFieldId, "Date");
fields.Add(navigationTitleFieldId, "NavigationTitle");
var data = new ItemData(def, Language.Parse("en"),new Sitecore.Data.Version(1), fields);
var dateTime = GetPublicationDate(hubSpotResult.publish_date).ToString();
var sitecoreStyleDateTime = DateUtil.ParseDateTime(dateTime,DateTime.Now);
Item item;
using (new SecurityDisabler())
{
item = new Item(id, data, webDb);
item.Editing.BeginEdit();
item.Fields["Date"].Value =DateUtil.ToIsoDate(sitecoreStyleDateTime.Date);
item.Fields["Title"].Value = hubSpotResult.html_title;
item.Fields["NavigationTitle"].Value = hubSpotResult.html_title;
Sitecore.Data.Fields.LinkField link = item.Fields["NavigationTitle"];
link.Url = hubSpotResult.url;
link.Text = hubSpotResult.html_title;
item.Editing.EndEdit();
}
return item;
}
Currently, I can't get the Url to the items that are created in this way as the the items don't exist on the Sitecore tree, however to render the link I need to set the Url of the item to point to the cloud server.
Is there a good way to Set the Url, so LinkManager.GetItemUrl(item) can get the url to the cloud server and also renders the title of the link or item?
The way to do this would be to override the LinkProvider with a custom one. When it see's an item based on the template you are using to create the "virtual" items, you can then use the data on that item to workout what the link to create should be. If the item is not of that template, then you can just pass it through to the base LinkProvider
public class MyLinkProvider : Sitecore.Links.LinkProvider
{
public override string GetItemUrl(Item item, UrlOptions options)
{
var templateID = new ID("<your template Id >");
if (item == null)
{
return string.Empty;
}
Assert.ArgumentNotNull(options, "options");
if (item.TemplateID == templateID)
{
// Build your custom url here
return "custom url";
}
else
{
return base.GetItemUrl(item, options);
}
}
}
Then patch that in via an include file:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<linkManager>
<providers>
<add name="sitecore">
<patch:attribute name="type">MyApplication.MyLinkProvider, MyApplication</patch:attribute>
</add>
</providers>
</linkManager>
</sitecore>
</configuration>
This will let normal items generate in the standard Sitecore way, and you can choose how the items link should be built.
I resolved my problem in quite an easier way.
I added a new field called Url with type of General Link to the template that I had created in Sitecore for these temporary virtual items.
I used it in my virtual item creation like this:
Sitecore.Data.Fields.LinkField link = item.Fields["Url"];
link.Url = hubSpotResult.url;
link.Text = hubSpotResult.html_title;
then, I grabbed the Url that I wanted in the same GetUrl extension like this:
if (i != null && i.Name == "HubSpotBlog")
{
LinkField link = i.Fields["Url"];
strUrl = link.Url;
}
the repeated took care of the rest of it and I was able to render values that I wanted on the view.

How to get the Page Id in my Facebook Application page

I have my application is hosted in FaceBook as a tab and I want to get the page ID when my application is being added to be stored in my logic.
How can I get the page ID, I know it is stored in the URL but when I tried to get it from the page as a server variable, I am not getting it even my application is configured as iFrame ? But this is a standard way to get the parent URL.
C#:
string t= request.serverVariables("HTTP_REFERER");
//doesn't get FB page url even if your app is configured as iframe ?!! #csharpsdk #facebook devs
Any help ?
Thanks a lot.
Here is how I do it:
if (FacebookWebContext.Current.SignedRequest != null)
{
dynamic data = FacebookWebContext.Current.SignedRequest.Data;
if (data.page != null)
{
var pageId = (String)data.page.id;
var isUserAdmin = (Boolean)data.page.admin;
var userLikesPage = (Boolean)data.page.liked;
}
else
{
// not on a page
}
}
The Page ID is not stored in the URL; it is posted to your page within the signed_request form parameter. See this Facebook developer blog post for more details.
You can use the FacebookSignedRequest.Parse method within the Facebook C# SDK to parse the signed request (using your app secret). Once you have done this you can extract the Page ID from the Page JSON object as follows:
string signedRequest = Request.Form["signed_request"];
var DecodedSignedRequest = FacebookSignedRequest.Parse(FacebookContext.Current.AppSecret, SignedRequest);
dynamic SignedRequestData = DecodedSignedRequest.Data;
var RawRequestData = (IDictionary<string, object>)SignedRequestData;
if (RawRequestData.ContainsKey("page") == true)
{
Facebook.JsonObject RawPageData = (Facebook.JsonObject)RawRequestData["page"];
if (RawPageData.ContainsKey("id") == true)
currentFacebookPageID = (string)RawPageData["id"];
}
Hope this helps.
Here's the same solution as Andy Sinclairs's in VB that worked for me:
Dim pageId as Int64 = 0
Dim signed_request As String = Request.Form("signed_request")
Dim req = FacebookSignedRequest.Parse(AppSettings("FacebookSecret"), signed_request)
Dim data As IDictionary(Of String, Object) = req.Data
If data.ContainsKey("page") Then
Dim RawPageData As Facebook.JsonObject = data("page")
If RawPageData.ContainsKey("id") Then
pageId = RawPageData("id")
End If
End If

Using the Facebook C# SDK for Fan Page Custom iFrame Tabs

I'm trying to create a simple iFrame custom tab on my fan page. I'm using the Facebook C# SDK and I need to read the signed_request value that Facebook passes to my iFrame page.
I can print the signed_request encoded value so I know its showing up, but when I try to decode it with the Facebook C# SDK I'm getting an error. I'm using .NET 4.0 and dynamics.
Here's my code:
signedRequestString contains the Request value with the signed_param passed from Facebook.
var result = FacebookSignedRequest.Parse(FacebookContext.Current.AppSecret, signedRequestString);
dynamic signedRequestJson = result.Data;
dynamic page = signedRequestJson.page;
And the error I receive:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot perform runtime binding on a null reference at CallSite.Target(Closure , CallSite , Object ) at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0) at DecodeSignedRequest(String signedRequestString)
Any thoughts why I would be getting a null? I setup my web.config properly (I think), but I'm guessing I'm missing an initialization step or something.
It's easier to use FacebookWebContext.Current.SignedRequest.
You can then access the information about the page:
if (FacebookWebContext.Current.SignedRequest != null)
{
dynamic data = FacebookWebContext.Current.SignedRequest.Data;
if (data.page != null)
{
var pageId = (String)data.page.id;
var isUserAdmin = (Boolean)data.page.admin;
var userLikesPage = (Boolean)data.page.liked;
}
else
{
// not on a page
}
}
You need to cast your signedRequestJson object to an IDictionary key/value pair before you can grab the page data.
You can do this as follows:
dynamic signedRequestJson = result.Data;
var RawRequestData = (IDictionary<string, object>)signedRequestJson;
You can then access the page data using the JSON keys (assuming you are referencing the Newtonsoft.Json.dll library):
Facebook.JsonObject RawPageData = (Facebook.JsonObject)RawRequestData["page"];
currentFacebookPageID = (string)RawPageData["id"];
Hope this helps.
I am using this. I hope it works for you:
Facebook.FacebookConfigurationSection s = new FacebookConfigurationSection();
s.AppId = 'ApplicationID';
s.AppSecret = 'ApplicationSecret';
FacebookWebContext wc = new FacebookWebContext(s);
dynamic da = wc.SignedRequest.Data;
dynamic page = da.page;
string pageid = page.id;
bool isLiked = page.liked;
bool isAdmin = page.admin;

Get Absolute URL from Relative path (refactored method)

I am really surprised that there is no native .NET method to get an absolute url from a relative url. I know this has been discussed many times, but never have come across a satisfactory method that handles this well. Can you help fine tune the method below?
I think all I need left is to auto choose the protocol instead of hard coding it (http/https). Anything else I am missing (caveats, performance, etc)?
public static string GetAbsoluteUrl(string url)
{
//VALIDATE INPUT FOR ALREADY ABSOLUTE URL
if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
|| url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
return url;
}
//GET PAGE REFERENCE FOR CONTEXT PROCESSING
Page page = HttpContext.Current.Handler as Page;
//RESOLVE PATH FOR APPLICATION BEFORE PROCESSING
if (url.StartsWith("~/"))
{
url = page.ResolveUrl(url);
}
//BUILD AND RETURN ABSOLUTE URL
return "http://" + page.Request.ServerVariables["SERVER_NAME"] + "/"
+ url.TrimStart('/');
}
This has always been my approach to this little nuisance. Note the use of VirtualPathUtility.ToAbsolute(relativeUrl) allows the method to be declared as an extension in a static class.
/// <summary>
/// Converts the provided app-relative path into an absolute Url containing the
/// full host name
/// </summary>
/// <param name="relativeUrl">App-Relative path</param>
/// <returns>Provided relativeUrl parameter as fully qualified Url</returns>
/// <example>~/path/to/foo to http://www.web.com/path/to/foo</example>
public static string ToAbsoluteUrl(this string relativeUrl) {
if (string.IsNullOrEmpty(relativeUrl))
return relativeUrl;
if (HttpContext.Current == null)
return relativeUrl;
if (relativeUrl.StartsWith("/"))
relativeUrl = relativeUrl.Insert(0, "~");
if (!relativeUrl.StartsWith("~/"))
relativeUrl = relativeUrl.Insert(0, "~/");
var url = HttpContext.Current.Request.Url;
var port = url.Port != 80 ? (":" + url.Port) : String.Empty;
return String.Format("{0}://{1}{2}{3}",
url.Scheme, url.Host, port, VirtualPathUtility.ToAbsolute(relativeUrl));
}
new System.Uri(Page.Request.Url, "/myRelativeUrl.aspx").AbsoluteUri
This one works for me...
new System.Uri(Page.Request.Url, ResolveClientUrl("~/mypage.aspx")).AbsoluteUri
With ASP.NET, you need to consider the reference point for a "relative URL" - is it relative to the page request, a user control, or if it is "relative" simply by virtue of using "~/"?
The Uri class contains a simple way to convert a relative URL to an absolute URL (given an absolute URL as the reference point for the relative URL):
var uri = new Uri(absoluteUrl, relativeUrl);
If relativeUrl is in fact an abolute URL, then the absoluteUrl is ignored.
The only question then remains what the reference point is, and whether "~/" URLs are allowed (the Uri constructor does not translate these).
Here is my own version that handles many validations and relative pathing from user's current location option. Feel free to refactor from here :)
/// <summary>
/// Converts the provided app-relative path into an absolute Url containing
/// the full host name
/// </summary>
/// <param name="relativeUrl">App-Relative path</param>
/// <returns>Provided relativeUrl parameter as fully qualified Url</returns>
/// <example>~/path/to/foo to http://www.web.com/path/to/foo</example>
public static string GetAbsoluteUrl(string relativeUrl)
{
//VALIDATE INPUT
if (String.IsNullOrEmpty(relativeUrl))
return String.Empty;
//VALIDATE INPUT FOR ALREADY ABSOLUTE URL
if (relativeUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
|| relativeUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
return relativeUrl;
//VALIDATE CONTEXT
if (HttpContext.Current == null)
return relativeUrl;
//GET CONTEXT OF CURRENT USER
HttpContext context = HttpContext.Current;
//FIX ROOT PATH TO APP ROOT PATH
if (relativeUrl.StartsWith("/"))
relativeUrl = relativeUrl.Insert(0, "~");
//GET RELATIVE PATH
Page page = context.Handler as Page;
if (page != null)
{
//USE PAGE IN CASE RELATIVE TO USER'S CURRENT LOCATION IS NEEDED
relativeUrl = page.ResolveUrl(relativeUrl);
}
else //OTHERWISE ASSUME WE WANT ROOT PATH
{
//PREPARE TO USE IN VIRTUAL PATH UTILITY
if (!relativeUrl.StartsWith("~/"))
relativeUrl = relativeUrl.Insert(0, "~/");
relativeUrl = VirtualPathUtility.ToAbsolute(relativeUrl);
}
var url = context.Request.Url;
var port = url.Port != 80 ? (":" + url.Port) : String.Empty;
//BUILD AND RETURN ABSOLUTE URL
return String.Format("{0}://{1}{2}{3}",
url.Scheme, url.Host, port, relativeUrl);
}
If you're in the context of an MVC Controller or View you can use the UrlHelper which should be accessible via just Url
Url.Content("~/content/images/myimage.jpg")
Which will be fully expanded to /virtual_directoryname/content/images/myimage.jpg
This can be used in a controller or .cshtml file
Yes it is a little odd that it's called Content but it's meant to be used to get an absolute path to a resource so it makes sense
Still nothing good enough using native stuff. Here is what I ended up with:
public static string GetAbsoluteUrl(string url)
{
//VALIDATE INPUT
if (String.IsNullOrEmpty(url))
{
return String.Empty;
}
//VALIDATE INPUT FOR ALREADY ABSOLUTE URL
if (url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
return url;
}
//GET CONTEXT OF CURRENT USER
HttpContext context = HttpContext.Current;
//RESOLVE PATH FOR APPLICATION BEFORE PROCESSING
if (url.StartsWith("~/"))
{
url = (context.Handler as Page).ResolveUrl(url);
}
//BUILD AND RETURN ABSOLUTE URL
string port = (context.Request.Url.Port != 80 && context.Request.Url.Port != 443) ? ":" + context.Request.Url.Port : String.Empty;
return context.Request.Url.Scheme + Uri.SchemeDelimiter + context.Request.Url.Host + port + "/" + url.TrimStart('/');
}
When you want to generate URL from your Business Logic layer, you do not have the flexibility of using ASP.NET Web Form's Page class/ Control's ResolveUrl(..) etc. Moreover, you may need to generate URL from ASP.NET MVC controller too where you not only miss the Web Form's ResolveUrl(..) method, but also you cannot get the Url.Action(..) even though Url.Action takes only Controller name and Action name, not the relative url.
I tried using
var uri = new Uri(absoluteUrl, relativeUrl)
approach, but there is a problem too. If the web application is hosted in IIS virtual directory, where the url of the app is like this : http://localhost/MyWebApplication1/, and the relative url is "/myPage" then the relative url is resolved as "http://localhost/MyPage" which is another problem.
Therefore, in order to overcome such problems, I have written a UrlUtils class which can work from a class library. So, it wont depend on Page class but it depends on ASP.NET MVC. So, if you dont mind adding reference to MVC dll to your class library project then my class will work smoothly. I have tested in IIS virtual directory scenario where the web application url is like this : http://localhost/MyWebApplication/MyPage. I realized that, sometimes we need to make sure that the Absolute url is SSL url or non SSL url. So, I wrote my class library supporting this option. I have restricted this class library so that the relative url can be absolute url or a relative url that starts with '~/'.
Using this library, I can call
string absoluteUrl = UrlUtils.MapUrl("~/Contact");
Returns : http://localhost/Contact
when the page url is : http://localhost/Home/About
Returns : http://localhost/MyWebApplication/Contact
when the page url is : http://localhost/MyWebApplication/Home/About
string absoluteUrl = UrlUtils.MapUrl("~/Contact", UrlUtils.UrlMapOptions.AlwaysSSL);
Returns : **https**://localhost/MyWebApplication/Contact
when the page url is : http://localhost/MyWebApplication/Home/About
Here is my class Library :
public class UrlUtils
{
public enum UrlMapOptions
{
AlwaysNonSSL,
AlwaysSSL,
BasedOnCurrentScheme
}
public static string MapUrl(string relativeUrl, UrlMapOptions option = UrlMapOptions.BasedOnCurrentScheme)
{
if (relativeUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
relativeUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
return relativeUrl;
if (!relativeUrl.StartsWith("~/"))
throw new Exception("The relative url must start with ~/");
UrlHelper theHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
string theAbsoluteUrl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority) +
theHelper.Content(relativeUrl);
switch (option)
{
case UrlMapOptions.AlwaysNonSSL:
{
return theAbsoluteUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
? string.Format("http://{0}", theAbsoluteUrl.Remove(0, 8))
: theAbsoluteUrl;
}
case UrlMapOptions.AlwaysSSL:
{
return theAbsoluteUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
? theAbsoluteUrl
: string.Format("https://{0}", theAbsoluteUrl.Remove(0, 7));
}
}
return theAbsoluteUrl;
}
}
The final version taking care of all previous complaints (ports, logical url, relative url, existing absolute url...etc.) considering the current handler is the page:
public static string ConvertToAbsoluteUrl(string url)
{
if (!IsAbsoluteUrl(url))
{
if (HttpContext.Current != null && HttpContext.Current.Request != null && HttpContext.Current.Handler is System.Web.UI.Page)
{
var originalUrl = HttpContext.Current.Request.Url;
return string.Format("{0}://{1}{2}{3}", originalUrl.Scheme, originalUrl.Host, !originalUrl.IsDefaultPort ? (":" + originalUrl.Port) : string.Empty, ((System.Web.UI.Page)HttpContext.Current.Handler).ResolveUrl(url));
}
throw new Exception("Invalid context!");
}
else
return url;
}
private static bool IsAbsoluteUrl(string url)
{
Uri result;
return Uri.TryCreate(url, UriKind.Absolute, out result);
}
check the following code to retrieve absolute Url :
Page.Request.Url.AbsoluteUri
I hope to be useful.
This works fine too:
HttpContext.Current.Server.MapPath(relativePath)
Where relative path is something like "~/foo/file.jpg"

How do I disable comments and ratings using the YouTube API asp.net

Any help would be much appreciated!
Current code:
YouTubeRequest request = Connect();
Video video = new Video();
video.Tags.Add(new MediaCategory("Nonprofit", YouTubeNameTable.CategorySchema));
video.Keywords = "Test";
video.YouTubeEntry.setYouTubeExtension("location", "UK");
The below method takes in a YouTube video retrieved from the YouTube request service and also takes in the type of permission and the new permissions.
private Video SetAccessControl(Video video, string type, string permission)
{
var exts = video.YouTubeEntry
.ExtensionElements
.Where(x => x is XmlExtension)
.Select(x => x as XmlExtension)
.Where(x => x.Node.Attributes["action"] != null && x.Node.Attributes["action"].InnerText == type);
var ext = exts.FirstOrDefault();
if (ext != null)
ext.Node.Attributes["permission"].InnerText = permission;
return video;
}
NOTE this will only work on a retrieved video, not if you pass in a "new Video()"
what it does is, iterates over all the ExtentionElements that you tube returned as part of the feed, and extracts the xml extension elements (as there isn't a build in c# access control extension) takes the elements that match where the action == type then updates the permissions attribute to the required value.
When the video entry is sent and updated to the YouTube server the updated access control elements are sent back and with the update request.
According to the Youtube API blog, you do it using the <yt:accessControl> tag, read here for more info.
e.g.
<yt:accessControl action='comment' permission='denied'/
Youtube API Blog Disable Comments Announcement
update youtube video status fron UNLISTED to Public
YouTubeRequestSettings settings = new YouTubeRequestSettings(_application, _developerkey, _username, _password);
Uri videoEntryUrl = new Uri("https://gdata.youtube.com/feeds/api/users/default/uploads/" + VideoID);
YouTubeRequest Request = new YouTubeRequest(settings);
Video Video = Request.Retrieve<Video>(videoEntryUrl);
List<Google.GData.YouTube.YtAccessControl> AccessControlsArray = Video.YouTubeEntry.AccessControls.ToList();
foreach (var item in AccessControlsArray)
{
if (item.Attributes["action"].ToString()=="list")
{
item.Attributes["permission"]= "allowed";
}
}
Video = Request.Update(Video);

Categories

Resources