Get the item matching a URL in Sitecore - sitecore

In a site I'm building, I'm trying to use the referer to verify AJAX requests are coming from the correct URLs.
To do this I'd like to get Sitecore to resolve a URL to an Item. For example,
http://www.mysite.com/abc/def
might resolve to the item at the path
sitecore/Content/MySite/Home/abc/def
What's the recommended way to go about this in my code?

Thanks for all the answers but none of them did everything I needed. This worked for me.
var url = new Uri(...);
// Obtain a SiteContext for the host and virtual path
var siteContext = SiteContextFactory.GetSiteContext(url.Host, url.PathAndQuery);
// Get the path to the Home item
var homePath = siteContext.StartPath;
if (!homePath.EndsWith("/"))
homePath += "/";
// Get the path to the item, removing virtual path if any
var itemPath = MainUtil.DecodeName(url.AbsolutePath);
if (itemPath.StartsWith(siteContext.VirtualFolder))
itemPath = itemPath.Remove(0,siteContext.VirtualFolder.Length);
// Obtain the item
var fullPath = homePath + itemPath;
var item = siteContext.Database.GetItem(fullPath);

This answer is more for other visitors hitting this SO question. In case of Sitecore 8 you could do this:
new Sitecore.Data.ItemResolvers.ContentItemPathResolver().ResolveItem(<string path>)
Where <string path> is like any local path (or relative url, if you will) string that sitecore would be able to generate for you. When using displayname values instead of item names (possibly the case if you have a multilingual site), this is very handy to actually retrieve the corresponding Item from database.
In my case I use this to show a valid breadcrumb where the parent paths DO have the context language item version added, but the requested page has no context language version to render. Sitecore.Context.Database.GetItem(<string path>) couldn't resolve the displayname-based path, while the ResolveItem method does... searched a day for a good answer on this case.
Questioning myself now, why this isn't used much...?
Maybe it is an expensive query for a site with a big tree. That is something to consider yourself.

Don't really get what you're trying to do (with your AJAX request and such), but if you want http://www.mysite.com/abc/def to resolve the item sitecore/content/MySite/Home/abc/def, you need to configure your <site> in the web.config like this:
<site name="MySite" hostName="www.mysite.com" rootPath="/sitecore/content/MySite" startItem="/Home" *other attributes here* />

You can use the method ItemManager.GetItem(itemPath, language, version, database, securityCheck) To resolve an item based on it's (full)path.

Related

How to get Zomato restaurant ID using restaurant link?

I want to get details of a restaurant in Zomato. I have it's link as the input (https://www.zomato.com/mumbai/fantasy-the-cake-shop-kalyan?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1). By browsing the documentation of Zomato APIs, I didn't found a way to get it.
I tried searching for the restaurant using search API but it returns many results.
Any help will be appreciated
It's a two-step process:
Find out restaurant's city id, in your case, Mumbai's city id through the /cities API. It's a simple query search.
Use the city id from the above API call in the /search API, like, https://developers.zomato.com/api/v2.1/search?entity_type=city&entity_id=3&q=fantasy%20the%20cake%20shop%20kalyan
This would give all the basic information about a restaurant.
View the page's source and search for window.RES_ID
I had the same issue as you described. This Zomato's API approach is at least odd. It's almost immposible to GET any information about restaurant if you don't know res_id in advance and that's not possible to parse since Zomato will deny access.
This worked for me:
Obtain user-key from Zomato API Credentials (https://developers.zomato.com/api)
Search restaurant url via API (https://developers.zomato.com/api/v2.1/search?entity_id=84&entity_type=city&q=RESTAURANT_URL&category=7%2C9). The more specific you will be, the better results you'll get (This url is specified by city to Prague (ID = 84) and categories Daily menus (ID = 7) and Lunch (ID = 9). If there is possibility do specify city, category or cuisine, it helps, but should't be necessary. Don't forget to define GET method in headers.
Loop or filter through json results and search for the wanted url. You might need to use method valueOf() to search for the same url. Be careful, you might need to add "?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1" at the end of your wanted url so it has the same format. Check that through Zomato API Documentation page.
for (i in body.restaurants) {
var url_wanted = restaurant_url + '?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1'
var url_in_json = body.restaurants[i].restaurant.url;
if (url_wanted.valueOf() == url_in_json.valueOf()) {
var restaurant_id = body.restaurants[i].restaurant.id;
}
console.log('Voala! We have res_id:' + restaurant_id);
}
There you have it. It could be easier though.
Hope it helps!
once you have the url of the rseraunt's page you can simply look for a javascript object attribute named "window.RES_ID" and further use it in the api call.

Sitecore PDF Not Downloading

I have a couple of unversioned PDFs in the media library... when I try opening them up from their URLs, it says "Layout not found". When I assign a layout (any layout), it just doesn't render anything.
I've added forcedownload=true to the media library section of the web.config... is there anything I'm missing? I thought this was supposed to download by default
http://testsite.org/sitecore/media%20library/pdfs/Publications/Periodicals/Test
The URL above basically doesn't work
Links to items in the media library are usually prefixed with /~/media/, unless you have changed the value of Media.MediaLinkPrefix in config. The link should be something like:
http://testsite.org/~/media/pdfs/Publications/Periodicals/Test.pdf
Make sure you are generating the URLs using MediaManager.GetMediaUrl()
FileField fileField = Sitecore.Context.Item.Fields["File Field"];
var mediaItem = new MediaItem(fileField.MediaItem);
string url = Sitecore.StringUtil.EnsurePrefix('/', MediaManager.GetMediaUrl(fileMediaItem));
Always use LinkManager.GetItemUrl() for items and MediaManager.GetMediaUrl() for media items to generate Sitecore URLs.
http://briancaos.wordpress.com/2012/08/24/sitecore-links-with-linkmanager-and-mediamanager/
http://corecompetency.tohams.com/index.php/linking-to-an-image-or-file-in-the-media-library/
You don't have to assign a layout to media item. Make sure you add "/" prefix before the url. Ex: site/~/media/path to pdf.ashx.
Also make sure you have media files published.
//below is the code to specify an Image URL
MediaItem mediaItem = new MediaItem(Sitecore.Context.Database.GetItem("Path"));
if (mediaItem != null)
{
imgBtn.ImageUrl = Sitecore.StringUtil.EnsurePrefix('/', Sitecore.Resources.Media.MediaManager.GetMediaUrl(mediaItem);
imgBtn.AlternateText = mediaItem.Alt;
}

sending query based on current route

Current solution:
example url:
http://localhost:3000/credit_cards?category=3
Application Route:
#controllerFor('creditCards').set 'content', App.CreditCard.find(category_id: getUrlParam('category'))
Get Url Params helper:
window.getUrlParam = (name) ->
paramsString = $(location).attr('search').substring(1)
urlParamsArray = paramsString.split('&')
for param in urlParamsArray
paramPair = param.split('=')
paramName = paramPair[0]
paramValue = paramPair[1]
return paramValue if paramName is name
Is there something better? Does Ember have it built-in out of the box?
Please note that Ember app is only a part of the app - it sits under its own root container. All the other elements are static.
Is there something better?
Depends. I'm assuming you need the query parameter because ember app is only part of your app. In that case your solution seems like a good one. Otherwise using a url like /credit_cards/3 instead would be better.
Does Ember have it built-in out of the box?
No. There is an experimental library available:
https://github.com/alexspeller/ember-query
Seems that might be overkill given how simple your example is, but if you are doing a lot of work with queryString I would recommend checking it out.

Using cookies to filter data in Google Analytics

I am trying to filter Google Analytics data for my company site based on a cookie. I don't want to track internal traffic, but I can't just filter based on an IP address range because there are some internal users who we want to still track. I have some pretty simple code for adding a cookie, but I am just not sure where to add the code. I am really new to cookies, and couldn't find anything online that was clear on how to actually add or use the cookie.
<html>
<head>
<title>Remove My Internal Traffic from Google Analytics</title>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-XXXXX-YY']);
_gaq.push(['_setVar','employee']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
So my question is, where does this code actually go? Thanks for helping out my novice skills with cookies.
Do not use setVar (this is deprecated), use _setCustomVar:
_setCustomVar(index, name, value, opt_scope)
The call goes before the _trackPageview Call.
There are five custom vars in standard GA (50 in premium), that's "index". 'Name' and 'value' should be clear.
CustomVars are either valid for the current page, for the session or for the visitor (in the last case they are valid until the visitors clears the cookies in his browsers unless he waits six months before he visits you site again).
Like every instruction with the asynonchronous GA code this is "pushed" on the gaq-Array, so the correct call would be:
_gaq.push(['_setCustomVar',
1, // This custom var is set to slot #1. Required parameter.
'Items Removed', // The name acts as a kind of category for the user activity. Required parameter.
'Yes', // This value of the custom variable. Required parameter.
2 // Sets the scope to session-level. Optional parameter.
]);
which is taken from the Google documentation here:
https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingCustomVariables#setup.
I still maintain that for your use case the opt-out plugin is the better solution.
UPDATE: Thinking about it I don't think you need setCustomVar or custom cookies at all. Have your employees go to your website via a link like:
mywebsite.com?utm_source=allyourbasearebelongtous
Then go to the profile settings and create a custom filter, set to exclude, filter field "campaign source" , filter pattern "allyourbasearebelongtous" (or whatever name you gave to your campaign parameter).
This uses also a cookie (the standard google cookie) but does not need any custom code at all. The campaign source parameter is valid until they visit another campaign geared towards your site, so if somebody wants to test the GA code they need to delete their cookies or use incognito mode (but that't not different from setting a custom cookie or setCustomVar-methods).

Search value in body tag in Sitecore

I want to implement search functionality, So my requirement is I want to search some keyword in body tag in all content page. I do not know how I can search keyword in body tag in Sitecore. Please guide me?
As Anton outlined, the concept of searching the Body tag is wrong for Sitecore. You want to think in terms of Content in fields of Items. Sitecore's ContentSearch is how you can achieve this.
Sitecore comes with default indexes out-of-the-box that you should use for the search. You should rebuild these via the Index Manager in the Content Editor and then base your search on the basic example I've outlined for you below.
public IEnumerable<Item> Search(string searchterm)
{
string indexName = "sitecore_web_index";
using (var index = ContentSearchManager.GetIndex(indexName).CreateSearchContext())
{
var predicate = PredicateBuilder.True<SearchResultItem>();
IQueryable<SearchResultItem> query = index.GetQueryable<SearchResultItem>().Where(i => i.Content.Contains(searchterm)).Filter(predicate);
var searchResults = query.GetResults();
foreach (var hit in searchResults.Hits)
{
yield return hit.Document.GetItem();
}
}
}
jRobbins's answer is sensible (he get's my upvote). However, it is technically possible to index the content of the body tag. I would be cautious with this. I've seen it working well, but I've also seen it completely destroy the performance of a site.
The approach involves the creating a computed field in your index. You populate the computed field by making a web request to your newly published page and scraping the response body tag.
Here's are a couple of module that more or less does that:
https://github.com/efocus-nl/sitecorewebsearch
https://github.com/hermanussen/sitecore-html-crawler
If you can accept something a little less accurate, then you could loop through each of the components on your page and extract content from their datasources. That approach is discussed in this video:
http://www.techphoria414.com/Blog/2012/May/Sitecore_Page_Editor_Unleashed