We are using the ADO.NET Data Service Provider Toolkit to implement a custom OData service endpoint running inside SharePoint 2010 (using .NET 3.5).
When the service is accessed in the root of a site collection the returned base address is correct, e.g.,
http://localhost/_vti_bin/service.svc/ returns a base address (in the returned atom document) as <feed xml:base="http://localhost/_vti_bin/service.svc />
But when the service endpoint is accessed in a subsite, the additional path segments are ignored, e.g.
http://localhost/subsite/_vti_bin/service.svc/ returns a base address (in the returned atom document) as <feed xml:base="http://localhost/_vti_bin/service.svc />
Unfortunately, this incorrect behavior confuses PowerPivot (which seem to use the returned base address to access subsequent queries).
Is there a way to explicitly the xml:base attribute from within the provider code?
This can be corrected by using the same IDispatchMessageInspector trick (as used by Pablo Castro to support JSON formatting) and adding the following code:
HttpRequestMessageProperty httpmsg = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
UriTemplateMatch match = (UriTemplateMatch)request.Properties["UriTemplateMatchResults"];
match.RequestUri = new Uri(SPContext.Current.Web.Url + match.RequestUri.PathAndQuery, UriKind.Absolute);
match.BaseUri = new Uri(SPContext.Current.Web.Url + match.BaseUri.AbsolutePath, UriKind.Absolute);
which basically changes the Base and Request Uris to include the subsite path.
Related
I am using the Java jclouds API for access to my Rackspace cloud files account.
I can create and list containers, and upload objects, but I can't figure out how to get the public links for an uploaded object. (I can see these public links from within the Rackspace control panel, by right-clicking on the object - there are 4 types: HTTP, HTTPS, Streaming, iOS Streaming).
The closest I can get is by using object.getInfo() to get the object's metadata. This includes a URI, but this doesn't resemble the public links I find from within the control panel.
Anyone know what I'm doing wrong?
I figured it out...
First, I should get the public URI of the object's container, not from the object.
Then I use a CloudFilesClient object. On the container I need to use getCDNMetadata("containername").getCDNUri()
Here is more information and some sample code to get the specific file CDN address.
For more details you can checkout the Java guide:
https://developer.rackspace.com/docs/cloud-files/quickstart/?lang=java
First get the cloud files api:
CloudFilesApi cloudFilesApi = ContextBuilder.newBuilder("rackspace-cloudfiles-us")
.credentials("{username}", "{apiKey}")
.buildApi(CloudFilesApi.class);
From there you can query the container:
CDNApi cdnApi = cloudFilesApi.getCDNApi("{region}");
CDNContainer cdnContainer = cdnApi.get("{containerName}");
Now with that CDNContainer you can get the specific web address that you need:
URI httpURI = cdnContainer.getUri();
URI httpsURI = cdnContainer.getSslUri();
This will get you the base URI for the container. Now to get the final address for your specific file you will need to append /{"your_file_name.extension"} to the end of the address. For example if my base URI was converted to a URL then to a String it may look like:
http://123456asdf-qwert987653.rackcdn.com/
From here I can get a file with the name example.mp4 with the following address:
http://123456asdf-qwert987653.rackcdn.com/example.mp4
This all assumes that you have already enabled CDN on the container.
I have simple route map like:
routes.MapRoute("Test", "test/{action}/{id}", new {controller = "Test", action = "Index", id = ""});
My route paths are like:
"/test/do-something/1.0.1"
Which works completely fine in local testing and self hosted .NET 4.5 on IIS7+
However, when I host it in Azure, it seems to have issues with the ID containing two ".", telling me that "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.".
When I change the path to "/test/do-something/1" it works on Azure as well.
Why does Azure seem to prohibit ID's with "." and what can I do about it?
I would recommend using '-' in your id as opposed to '.' (periods), it's more friendly in terms of SEO.
If you really want to get it working with periods, you could use a tool called URLScan.
What is URLScan?
There is an option to configure:
AllowDotInPath=0
By default, this option is set to 0. If this option is set to 0,
URLScan rejects any request that contains multiple periods (.). This
prevents attempts to disguise requests for dangerous file name
extensions by putting a safe file name extension in the path
information or query string portion of the URL. For example, if this
option...
Here is a link to the configuration.
I am looking to serve an image from my root path test.com/some.png but this markdown page may be displayed on [Post]test.com/Item or [Put]test.com/Item/123 So I am looking for a way to get the base URI to form the image link.
You can use the literal text ~/ inside a Markdown page gets converted to a virtual path.
This literal is registered on start-up from the global EndpointHostConfig.MarkdownReplaceTokens property which is assigned the appHost.Config.WebHostUrl property:
this.MarkdownReplaceTokens["~/"] = appHost.Config.WebHostUrl.WithTrailingSlash();
Since it's difficult for an ASP.NET framework to determine the url its hosted at (i.e. without a request) you need to specify the preferred url you wan to use in your config. Here's an example from the servicestack.net/docs/ - ServiceStack's markdown Docs project:
SetConfig(new EndpointHostConfig {
WebHostUrl = baseUrl, //replaces ~/ with Url
MarkdownBaseType = typeof(CustomMarkdownPage),
});
Otherwise inside your service you can use base.Request or base.RequestContext.Get<IHttpRequest>() to get information about the incoming Request as well as (HttpRequest)base.Request.OriginalRequest to get the underlying ASP.NET Request object.
i'm trying to get the list of mime types known to an IIS server (which you can see was asked and and answered by me 2 years ago). The copy-pasted answer involves:
GetObject("IIS://LocalHost/MimeMap") msdn
GetObject("IIS://localhost/mimemap") KB246068
GetObject("IIS://localhost/MimeMap") Scott Hanselman's Blog
new DirectoryEntry("IIS://Localhost/MimeMap")) Stack Overflow
new DirectoryEntry("IIS://Localhost/MimeMap")) Stack Overflow
New DirectoryServices.DirectoryEntry("IIS://localhost/MimeMap") Velocity Reviews
You get the idea. Everyone agrees that you use a magical path iis://localhost/mimemap. And this works great, except for the times when it doesn't.
The only clue i can find as to why it fails, is from an IIS MVP, Chris Crowe's, blog:
string ServerName = "LocalHost";
string MetabasePath = "IIS://" + ServerName + "/MimeMap";
// Note: This could also be something like
// string MetabasePath = "IIS://" + ServerName + "/w3svc/1/root";
DirectoryEntry MimeMap = new DirectoryEntry(MetabasePath);
There are two clues here:
He calls iis://localhost/mimemap the Metabase Path. Which sounds to me like it is some sort of "path" to a "metabase".
He says that the path to the metabase could be something else; and he gives an example of what it could be like.
Right now i, and the entire planet, are hardcoding the "MetabasePath" as
iis://localhost/MimeMap
What should it really be? What should the code be doing to construct a valid MetabasePath?
Note: i'm not getting an access denied error, the error is the same when you have an invalid MetabasePath, e.g. iis://localhost/SoTiredOfThis
If you're working with the IIS config of your local machine i.e. your code and IIS are on the same box then it's sufficient to specify:
IIS://Localhost/mimemap
The IIS: portion is also known as a moniker in OLE parlance.
If you open the IIS6 metabase file (C:\Windows\System32\inetsrv\metabase.xml) you'll find a large 'blob' of XML. This is in fact a flattened out tree structure.
Paths in the metabase are represented by Location attributes.
The moniker IIS://localhost maps to the Location path /LM which is effectively the tree root.
The moniker IIS://localhost/MimeMap maps to the Location path /LM/MimeMap.
If your code is accessing the metabase on remote machines then instead of specifiying IIS://localhost/[path], one would specify IIS://[RemoteMachineName]/[path]. This is what Chris Crowes comment means.
IIS://localhost/MimeMap is also the master Mime Type list. All sites inherit this list (the IIS Metabase relies heavily on inherited properties).
If you wanted to override the Mime types for a specific site then you'd modify:
IIS://localhost/W3SVC/[iisnumber]/ROOT/MimeMap
It's useful to open up the IIS metabase file and have a dig around to understand what's going on under the bonnet.
Update:
To answer your question about why you can create a DirectoryEntry object where the path is invalid, DirectoryEntry is a general purpose wrapper object used to bind against different types of ADSI providers such as IIS, LDAP and WinNT. It permits creation of DirectoryEntry objects where there may not necessarily be a matching object at the path specified. Some ADSI provider operations may require this capability.
There is a static method on DirectoryEntry called Exists that you can use to test for the existence of objects. For example:
// Does Default Website exist?
if(DirectoryEntry.Exists("IIS://localhost/w3svc/1"))
{
// Do work...
}
I was having a problem with getting 0x80005000 returned when trying to do this. The stupid cause of my problem was that I was using IIS7 and hadn't installed IIS6 metabase compatibility support.
When using RIA services, how do I specify I want to use OData instead of a proprietary format?
I'm new with Odata but currently works on RIA and I found the article from Brad Abrams blog at
http://blogs.msdn.com/brada/archive/2010/03/16/silverlight-4-ria-services-ready-for-business-exposing-odata-services.aspx
After finished prepare everything such a service, you can specify to use OData by calling URL to the DomainService like
"http://localhost:7777/Sample-App-GreatDomainService.svc/OData/YourObject"
Which,
Sample-App-GreatDomainService.svc = Your domainservice namespace(Mine is Sample.App.GreatDomainService) and followed by .svc (see that '.' replaced by '-')
/OData/YourObject = Exposed to the typename in your data model as OData (Mine is "YourObject" type)
This will get an Atom Feed data of type "YourObject" in your project.
Hop this help. ^ ^