Retrieving the parent URI of a BluePrinted component based on the URI of a child component - tridion

Does anyone know how can I find the URI of a parent Component based on the URI of a shared or localized component in a child publication in SDL Tridion using the Core Service?

You can use ComponentData.BluePrintInfo.OwningRepository.IdRef to get the TcmUri of the publication that "owns" that component. This is the first publication "going up" where the component is either created or localized.
Then you can use something like this to get you the component Uri in the right context:
internal string GetUriInBlueprintContext(string itemId, string publicationId)
{
if (TcmUri.UriNull == itemId)
return null;
TcmUri itemUri = new TcmUri(itemId);
TcmUri publicationUri = new TcmUri(publicationId);
TcmUri inContext = new TcmUri(itemUri.ItemId, itemUri.ItemType, publicationUri.ItemId);
return inContext.ToString();
}
The TcmUri class is part of the Tridion.Common.dll which you can reference from your project too.

Here's is simpler approach than the one that Nuno is proposing and you don't need to reference any dlls
var parentComponentid = ClientAdmin.GetTcmUri(component.Id, component.BluePrintInfo.OwningRepository.IdRef, null);
GetTcmUri method is good for getting any TcmUris - just pass publication id you want your item in and Id of item in current publication. This way you can also find ID of a given item in particular child publication

Related

Disassemble links into entities in Spring Hateoas

maybe another one stumbled upon this topic and found a nice solution. Using the HATEOAS REST approach with help of Spring HATEOAS project works pretty well for link building to resources. But in the end, to map flattened resources back to an entity object tree, I need to disassemble my link and query the persistence backend. Example given, I have an entity Item, referencing ItemType (Many-to-one). Natural key of item is the composite of ItemType foreign key and Item code itself. The URL I map in ItemController using the link builder is
#RequestMapping("/catalog/items/{itemTypeCode}_{itemCode}")
Now a unique link for an item is e.g. http://www.sample.com/catalog/items/p_abc123
To invert this link I do some very ugly string work:
#Override
public Item fromLink(Link link) {
Assert.notNull(link);
String baseLink = linkTo(ColorTypeController.class).toString() + "/";
String itemTypeAndItemPart = link.getHref().replace(baseLink, "");
int indexOfSplit = itemTypeAndItemPart.indexOf('_');
ItemType itemType = new ItemType();
itemType.setCode(itemTypeAndItemPart.substring(0, indexOfSplit));
Item item = new Item();
item.setItemType(itemType);
item.setCode(itemTypeAndItemPart.substring(indexOfSplit + 1));
return item;
}
And all the time I am wondering, If there isn't a much nicer and more flexible approach (beware of any query string part, that will break the code) to do this inverse mapping. I actually do not want to call another MVC controller from within a controller but it would be nice, to somehow utilize the dispatcher servlet disassembly functions to deconstruct the URL into something more handy to work with. Any helpful hints for me? Thx alot :)
You can use a UriTemplate. Its match method returns a map of variables and their values that have been extracted from the URI. For example:
UriTemplate uriTemplate = new UriTemplate("/catalog/items/{itemTypeCode}_{itemCode}");
Map<String, String> variables = uriTemplate.match("http://www.sample.com/catalog/items/p_abc123");
String itemTypeCode = variables.get("itemTypeCode"); // "p"
String itemCode = variables.get("itemCode"); // "abc123"

how to hide metadata in web api 2, odata

I have defined odata route using MapODataServiceRoute in my WebApiConfig.
config.Routes.MapODataServiceRoute("CompanyoOdata", "odata", GetImplicitEdm(config));
private static IEdmModel GetImplicitEdm(HttpConfiguration config)
{
ODataModelBuilder builder = new ODataConventionModelBuilder(config, true);
builder.EntitySet<Company>("Company");
builder.EntitySet<Photo>("Photos");
builder.EntitySet<Country>("Country");
return builder.GetEdmModel();
}
The data service works just fine. But I want to achieve few things.
I don't want to expose my metadata or associations because i'm using it internally and will not need metadata. How can I restrict access to these information (i.e restrict access to http://www.sample.com/odata/#metadata or http://www.sample.com/odata/$metadata)
secondly, I want to ignore some properties from getting serialized. I found two ways of doing this.
Using data contracts and marking properties with [DataMember] attribute or [IgnoreDataMember] attribute
Using Ignore method on EntitySet when building the model
I can't use the first method as I'm using Database first approach for entity framework hence can't decorate the entity with attributes. I thought I can achieve this by using MetaDataType, but it seems it only works for DataAnnotations.
I used second method with success, but you can't pass more than one property in the ignore method. Has to do it to individual property that I need to ignore, which is a bit tedious. Is there another way to do this?
any help really appreciated.
If want to hide metadata (/$metadata) or service document (/), can remove the the MetadataRoutingConvention from existing routing conventions, e.g.:
var defaultConventions = ODataRoutingConventions.CreateDefault();
var conventions = defaultConventions.Except(
defaultConventions.OfType<MetadataRoutingConvention>());
var route = config.MapODataServiceRoute(
"odata",
"odata",
model,
pathHandler: new DefaultODataPathHandler(),
routingConventions: conventions);
If only expose a few properties per type, can use ODataModelBuilder instead of ODataConventionModelBuilder. E.g., some example:
ODataModelBuilder builder = new ODataModelBuilder();
EntityTypeConfiguration<Customer> customer = builder.EntitySet<Customer>("Customers").EntityType;
customer.HasKey(c => c.Id);
customer.Property(c => c.Name);

Content-ID references in ASP.NET OData batch requests

I have an ASP.NET WebApi OData service, and I am trying to consume it from JavaScript using JayData.
My model is as follows:
class Parent {
ICollection<Child> Children;
}
class Child {
ICollection<Parent> Parents;
}
I'm trying to add a new parent entity with a new child entity using JayData context, something like:
var child = new db.Children.Child({Parents: []});
var parent = new db.Parents.Parent({Children: [child]});
db.Parents.add(parent);
db.saveChanges();
As a result, JayData sends a batch request to the OData service containing 2 post requests: one for the child and another for the parent, where the child is given Content-ID = 1,
and the parent entity is serialized to JSON as:
{'Children': [{'__metadata': {'uri': '$1'}}]}
On the server side, the CreateEntity method of both Parent and Child EntitySetControllers gets executed, but the Parent argument has an empty collection of Children, i.e. it ignores the Content-ID reference to the new Child entity from the request.
Is there a convenient way to make it work in ASP.NET OData, or do I have to parse the Parent's JSON from the request and check whether such references exist by hand?

Orchard CMS - determining if Model is valid in Content Item Driver

In my instance of Orchard, I have a custom content type which has a custom content part. In the "editor driver" for the content part, I need to check to see if the container content item is valid (i.e. passes validation).
The normal ModelState won't work here because of how Orchard works - and I can determine if the content part is valid, but I need to know about the entire content item (there are other content parts within the content item).
I know there are ways to execute code once a content part is published / created using lifecycle events (http://docs.orchardproject.net/Documentation/Understanding-content-handlers), but there's no way (that I know of) to pass those events information.
Basically, I need to execute a method if the content item is valid, and I need to pass the method information contained within the ViewModel.
There may be (and probably is) a better way to do this, but I'm struggling to find a way within Orchards framework.
sample code:
//POST
protected override DriverResult Editor(EventPart part, IUpdateModel updater, dynamic shapeHelper)
{
var viewModal = new EventEditViewModel();
if (updater.TryUpdateModel(viewModal, Prefix, null, null))
{
part.Setting = viewModal.Setting;
}
//here's where I need to check if the CONTENT ITEM is valid or not, for example
if (*valid*)
{
DoSomething(viewModal.OtherSetting);
}
return Editor(part, shapeHelper);
}
Note: I am using Orchard version 1.6.
No easy way to do that from inside a driver, I'm afraid. Too early. You can access other parts by doing part.As<OtherPart>, but those may or may not be updated yet at this point.
You may try utilizing handlers and OnPublishing/OnPublished (and other) events like this:
OnPublishing<MyPart>((ctx, part) =>
{
// Do some validation checks on other parts
if (part.As<SomeOtherPart>().SomeSetting == true)
{
notifier.Error(T("SomeSetting cannot be true."));
transactions.Cancel();
}
});
where transactions is ITransactionManager instance, injected in ctor.
If you need more control, writing your own controller for handling item updates/creates is the best way to go.
In order to do that (assuming you already have your controller in place), you need to use handler OnGetContentItemMetadata method to point Orchard to use your controller instead of the default one, like this:
OnGetContentItemMetadata<MyPart>((context, part) =>
{
// Edit item action
context.Metadata.EditorRouteValues = new RouteValueDictionary {
{"Area", "My.Module"},
{"Controller", "Item"},
{"Action", "Edit"},
{"id", context.ContentItem.Id}};
// Create new item action
context.Metadata.CreateRouteValues = new RouteValueDictionary {
{"Area", "My.Module"},
{"Controller", "Item"},
{"Action", "Create"});
});

RequestContext in composite control

I'm trying to access the route data within a composite control to change the directory lookup for images based on the section the user is browsing to.
e.g: http://www.mysite.com/photos/palmtrees
In this cause, {palmtrees} = {id} and I'd like to access this within a composite control.
I've read up about similar requirements but cannot seem to the get RequestContext to return anything but null?
// this.Context = HttpContext.Current;
HttpContextBase htb = new HttpContextWrapper(this.Context);
RequestContext rc = new RequestContext(htb, RouteTable.Routes.GetRouteData(htb));
// rc -> is always NULL?
Is there an easier way to get the RouteData within my control?
Jumping between routes was outside of the route context, meaning that RouteData was never available.
Ensured that when a user clicks on a button to take them to /photo/{id} the context of the route was activated.
Not using MVC, this is a Web Form project.

Resources