I am new to sitecore, when I try to create new item for existing template. I am unable to call my master database.Need some guide for how to create new item in sitecore and how to show it on my running sitecore page? Just need some hint regarding flow of after creation how to render it on existing sitecore page.
<configuration type="Sitecore.Search.SearchConfiguration, Sitecore.Kernel" singleInstance="true">
<indexes hint="list:AddIndex">
<index id="system" type="Sitecore.Search.Index, Sitecore.Kernel">
<param desc="name">$(id)</param>
<param desc="folder">__system</param>
<Analyzer ref="search/analyzer" />
<locations hint="list:AddCrawler">
<core type="Sitecore.Search.Crawlers.DatabaseCrawler,Sitecore.Kernel">
<Database>core</Database>
<Root>/sitecore/content</Root>
<include hint="list:IncludeTemplate">
<application>{EB06CEC0-5E2D-4DC4-875B-01ADCC577D13}</application>
</include>
<Tags>application</Tags>
<Boost>2.0</Boost>
</core>
<core-controlpanel type="Sitecore.Search.Crawlers.DatabaseCrawler,Sitecore.Kernel">
<Database>core</Database>
<Root>/sitecore/content/applications/control panel</Root>
<include hint="list:IncludeTemplate">
<taskoption>{BDB6FA46-2F76-4BDE-8138-52B56C2FC47E}</taskoption>
</include>
<Tags>taskoption</Tags>
<Boost>1.9</Boost>
</core-controlpanel>
<master type="Sitecore.Search.Crawlers.DatabaseCrawler, Sitecore.Kernel">
<Database>master</Database>
<Tags>master content</Tags>
</master>
</locations>
</index>
</indexes>
</configuration>
I will write the code I usually execute:
Database database = Database.GetDatabase("master");
Item rooItem = database.GetItem(new ID(parentItemId));
if (rootItem == null) return null;
TemplateID pageTemplateId = new TemplateID(new ID(templateId));
string validName = ItemUtil.ProposeValidItemName(name);
using (new Sitecore.SecurityModel.SecurityDisabler())
{
Item newItem = rootItem.Add(validName, pageTemplateId);
if (newItem == null) return null;
//TODO: publish item
}
rootItem could be the home item
templateId will be the id of your page template (remember this page should have layout and renderings defined)
Related
We upgraded our solution from Sitecore 8.1 Update 1 to Update 2. Our URL's are generated from display name and that was working fine.
But after upgrading, the behaviour changed to URL generation from item name although ShowConfig.aspx still shows "useDisplayName="true" for .
We're using the following config:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<linkManager defaultProvider="sitecore">
<providers>
<clear/>
<add name="sitecore">
<patch:attribute name="addAspxExtension">false</patch:attribute>
<patch:attribute name="useDisplayName">true</patch:attribute>
<patch:attribute name="languageEmbedding">never</patch:attribute>
<patch:attribute name="alwaysIncludeServerUrl">true</patch:attribute>
</add>
</providers>
</linkManager>
</sitecore>
Now all links only show a 404. What am I missing?
We tried on an empty solution and it's the same behaviour. So it is a Sitecore bug.
We contacted Sitecore Support. They introduced a new setting in Update 2 in Sitecore.config.
<setting name="ItemResolving.FindBestMatch" value="DeepScan" />
This setting needs to be set to:
<setting name="ItemResolving.FindBestMatch" value="Disabled" />
It was supposed to solve the following bug:
96805: Item could have been unresolved with specific encodeNameReplacement and wildcard/display name resolving logic
This is now registered as a bug with the reference number 105324.
I need to get a specific item based on it's displayname, how do I do that?
For example I want to get this item /sitecore/content/mysite/about
But on the site is translated to multiple languages and could be something like www.site.com/om (in Sitecore it would be /sitecore/content/mysite/om)
There are a couple approaches you can take. The most efficent is to leverage the Content Search API, but the challenge is that Display Name is excluded from the index by default. A simple patch file can fix this:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<indexConfigurations>
<defaultLuceneIndexConfiguration>
<exclude>
<__display_name>
<patch:delete />
</__display_name>
</exclude>
</defaultLuceneIndexConfiguration>
</indexConfigurations>
</contentSearch>
</sitecore>
</configuration>
Then your code would be something like:
public Item GetItemByDisplayName(string displayName)
{
var searchIndex = ContentSearchManager.GetIndex("sitecore_master_index"); // sub your index name
using (var context = searchIndex.CreateSearchContext())
{
var searchResultItems =
context.GetQueryable<SearchResultItem>().Where(i => i["Display Name"].Equals(displayName)).FirstOrDefault();
return searchResultItems == null ? null : searchResultItems.GetItem();
}
}
This all is assuming you are on Sitecore 7. If you're on Sitecore 6, your option are limited and are probably not going to perform well if you content tree is large. Nonetheless, your function might look like:
public Item GetItemByDisplayName(string displayName)
{
var query = string.Format("fast:/sitecore/content//*[#__Display Name='{0}']", displayName);
var item = Sitecore.Context.Database.SelectSingleItem(query);
return item;
}
Please note that this will be horribly inefficent since under the covers this is basically walking the content tree.
Often, you wouldn't need to. LinkManager (responsible for generating all your item URLs) has an option to base the URLs on Display Name instead of Item.Name.
var d = LinkManager.GetDefaultUrlOptions();
d.UseDisplayName = true;
This can also be configured in configuration. Find and amend this section in your Web.config (or patch it via include files):
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel"
addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true"
languageEmbedding="never" languageLocation="filePath" lowercaseUrls="true"
shortenUrls="true" useDisplayName="false" />
</providers>
</linkManager>
To truly do exactly what you ask is a quite involved process. If you point DotPeek to Sitecore.Pipelines.HttpRequest.ItemResolver, you can step through the ResolveUsingDisplayName() method. It essentially loops through child items, comparing the URL Part to the "__Display Name" field. You would have to cook up something similar.
I have integrated active directory module with sitecore, I am able to see the users from ad in sitecore user manager. Now i want to verify if the ad user can login to sitecore. I assigned sitecore\Sitecore Client Users role for the user and tried to login as
Username: domain\username
Password: pw
I see a wierd error when login button is hit. Below is the error.
But when i check the set as administrator check box for this user, i am able to login with
Username: domain\username
Password: pw
Any help is appreciated.
Thanks.
Server Error in '/' Application.
Creating an instance of the COM component with CLSID {080D0D78-F421-11D0-A36E-00C04FB950DC} from the IClassFactory failed due to the following error: 800401e4 Invalid syntax (Exception from HRESULT: 0x800401E4 (MK_E_SYNTAX)).
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Runtime.InteropServices.COMException: Creating an instance of the COM component with CLSID {080D0D78-F421-11D0-A36E-00C04FB950DC} from the IClassFactory failed due to the following error: 800401e4 Invalid syntax (Exception from HRESULT: 0x800401E4 (MK_E_SYNTAX)).
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[COMException (0x800401e4): Creating an instance of the COM component with CLSID {080D0D78-F421-11D0-A36E-00C04FB950DC} from the IClassFactory failed due to the following error: 800401e4 Invalid syntax (Exception from HRESULT: 0x800401E4 (MK_E_SYNTAX)).]
System.Web.Security.DirectoryInformation.GetADsPath(String dn) +108
System.Web.DataAccess.ActiveDirectoryConnectionHelper.GetDirectoryEntry(DirectoryInformation directoryInfo, String objectDN, Boolean revertImpersonation) +42
System.Web.Security.ActiveDirectoryMembershipProvider.ValidateUserCore(String username, String password) +1970
System.Web.Security.ActiveDirectoryMembershipProvider.ValidateUser(String username, String password) +39
LightLDAP.SitecoreADMembershipProvider.ValidateUser(String username, String password) +193
Sitecore.Data.DataProviders.NullRetryer.Execute(Func`1 action, Action recover) +394
Sitecore.Security.SitecoreMembershipProvider.ValidateUser(String username, String password) +319
System.Web.UI.WebControls.Login.AuthenticateUsingMembershipProvider(AuthenticateEventArgs e) +105
System.Web.UI.WebControls.Login.AttemptLogin() +160
System.Web.UI.WebControls.Login.OnBubbleEvent(Object source, EventArgs e) +93
System.Web.UI.Control.RaiseBubbleEvent(Object source, EventArgs args) +84
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3804
I came across similar issue for my one of my web app.
If you are still facing this problem, you can fix this by going to Advanced Settings of the IIS App pool of your application and setting "Load User Profile" option to True.
#MattGartman here are the membership and role poviders
<membership defaultProvider="sitecore" hashAlgorithmType="SHA1">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Security.SitecoreMembershipProvider, Sitecore.Kernel" realProviderName="switcher" providerWildcard="%" raiseEvents="true" />
<add name="sql" type="System.Web.Security.SqlMembershipProvider" connectionStringName="core" applicationName="sitecore" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="256" />
<add name="switcher" type="Sitecore.Security.SwitchingMembershipProvider, Sitecore.Kernel" applicationName="sitecore" mappings="switchingProviders/membership" />
<add name="ad" type="LightLDAP.SitecoreADMembershipProvider" connectionStringName="ADConnString" applicationName="sitecore" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" connectionUsername="domain\username" connectionPassword="pw" connectionProtection="Secure" attributeMapUsername="sAMAccountName" enableSearchMethods="true" customFilter="(memberOf=CN=RegionsComSitecore,OU=Groups,DC=c,DC=pk,DC=com)" />
</providers>
</membership>
<roleManager defaultProvider="sitecore" enabled="true">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Security.SitecoreRoleProvider, Sitecore.Kernel" realProviderName="switcher" raiseEvents="true" />
<add name="sql" type="System.Web.Security.SqlRoleProvider" connectionStringName="core" applicationName="sitecore" />
<add name="switcher" type="Sitecore.Security.SwitchingRoleProvider, Sitecore.Kernel" applicationName="sitecore" mappings="switchingProviders/roleManager" />
<add name="ad" type="LightLDAP.SitecoreADRoleProvider" connectionStringName="ADConnString" applicationName="sitecore" username=" domain\username" password="pw" attributeMapUsername="sAMAccountName" cacheSize="2MB" customFilter="(memberOf=CN=RegionsComSitecore,OU=Groups,DC=c,DC=pk,DC=com)" />
</providers>
</roleManager>
here is the ldap.config
<pipelines>
<initializeAdUserEntry>
<!--
Use the processor if all new user should have a predefiled value in a property.
The PropertyName parameter defines the name of the property.
The DefaultValue parameter defines the default value of the property.
-->
<!--
<processor type="LightLDAP.Pipelines.InitializeAdEntry.SetPropertyValue, LightLDAP">
<PropertyName desc="AD property name ">type the property name here</PropertyName>
<DefaultValue desc="AD property name ">type the default property value here</DefaultValue>
</processor>
-->
<!--
Use the processor if all new roles should be a member of the predefined role.
The RoleName parameter defines the name of the main role.
-->
<!--
<processor type="LightLDAP.Pipelines.InitializeAdEntry.AddToRole, LightLDAP">
<RoleName desc="AD group">type role name here</RoleName>
</processor>
-->
<processor type="LightLDAP.Pipelines.InitializeAdEntry.CommitChanges, LightLDAP"/>
</initializeAdUserEntry>
<initializeAdRoleEntry>
<!--
Use the processor if all new user should have a predefiled value in a property.
The PropertyName parameter defines the name of the property.
The DefaultValue parameter defines the default value of the property.
-->
<!--
<processor type="LightLDAP.Pipelines.InitializeAdEntry.SetPropertyValue, LightLDAP">
<PropertyName desc="AD property name ">type the property name here</PropertyName>
<DefaultValue desc="AD property value ">type the default property value here</DefaultValue>
</processor>
-->
<!--
Use the processor if all new roles should be a member of the predefined role.
The RoleName parameter defines the name of the main role.
-->
<!--
<processor type="LightLDAP.Pipelines.InitializeAdEntry.AddToRole, LightLDAP">
<RoleName desc="AD group">type role name here</RoleName>
</processor>
-->
<processor type="LightLDAP.Pipelines.InitializeAdEntry.CommitChanges, LightLDAP"/>
</initializeAdRoleEntry>
</pipelines>
<settings>
<!-- Defines the logging level of the module. If true, dumps every action entry into the log.
Default is false
-->
<setting name="LDAP.Debug" value="true" />
<!-- Defines if the configuration assumes indirect membership on common operations.
This setting affects the membership verification during login and user access check.
Default is false
-->
<setting name="LDAP.IncludeIndirectMembership" value="false" />
<!-- Defines if a certain profile should be applied for each user by default.
If the setting is not specified or is empty, no particular profile item is used.
Default is ""
-->
<!-- ENABLE SORT OPERATION
Determines whether the sorting is enabled
-->
<setting name="LDAP.EnableSorting" value="false" />
<!-- Default Sort Key-->
<setting name="LDAP.SortKey" value="codePage" />
<!-- LDAP GET ALL USERS SIZE LIMIT
Determines the max number of returned users for GetAll method
-->
<setting name="LDAP.SizeLimit" value="1000" />
<!-- LDAP FIND USERS SIZE LIMIT
Determines the max number of returned users for GetAll method
-->
<setting name="LDAP.FindSizeLimit" value="100" />
<!-- LDAP USER CACHE SIZE
Determines the size of the ldap users cache.
Specify the value in bytes or append the value with KB, MB or GB
A value of 0 (zero) disables the cache.
-->
<setting name="LDAP.Caching.UserCache" value="2MB" />
<!-- LDAP MEMBEROF CACHE SIZE
Determines the size of the ldap users cache.
Specify the value in bytes or append the value with KB, MB or GB
A value of 0 (zero) disables the cache.
-->
<setting name="LDAP.Caching.MemberOfCache" value="2MB" />
<!-- LDAP MEMBERS CACHE SIZE
Determines the size of the ldap users cache.
Specify the value in bytes or append the value with KB, MB or GB
A value of 0 (zero) disables the cache.
-->
<setting name="LDAP.Caching.MembersCache" value="2MB" />
<!-- SETTINGS PROPERTY VALUE FACTORY
Returns an SettingsPropertyValueFactory interface that resolves the active directory properties.
-->
<setting name="LDAP.SettingsPropertyValueFactory" value="LightLDAP.SettingsPropertyValueFactory, LightLDAP" />
<!-- RECONNECT PERIOD
Determines a reconnect period for attempts to restore connection after the connection gets break.
-->
<setting name="LDAP.ReconnectPeriod" value="0.00:00:10" />
<!-- TIME OUT NOTIFICATION
Determines a timeout for notification.
-->
<setting name="LDAP.NotificationTimeOut" value="1.00:00:00" />
<!-- FULL NAME PROPERTY NAME
Determines the full name property mapping.
-->
<setting name="LDAP.FullName" value="ad|unicode string|displayName" />
<!-- DELETE USER SCOPE
Determines the scope of the "delete user" operation.
-->
<setting name="LDAP.DeleteScope" value="Subtree" />
<!-- MAX VALUE RANGE
Determines the maximal value of an AD range attribute.
-->
<setting name="LDAP.MaxValueRange" value="1500" />
</settings>
For AD Enabled login, try login from /sitecore/admin/ldaplogin.aspx page.
I know this question is old, but I've had this issue recently and spent quite a bit of time researching the cause and solution via Microsoft docs, etc. There is sometimes an issue caused by the IIS refresh process when trying to access certain interfaces within com objects that are dynamically loaded from various DLL written in C++. These kind of DLLs/interfaces can be tricky and confusing. I have found that the best solution is to avoid some calls to the User Group principal objects that are given by this interface. If you are calling a method that looks something like: [Some user object].IsMemberOf([Some group object]). Try changing the code to avoid calling any function on the user object. From the example above, you could change the code to look like this:
foreach (var user in [Some group object].GetUsers())
{
if (user.SamAccountName == [Some user object].SamAccountName)
{
// Do your work here
}
}
Of course, the operations that you are performing in your code may not be the same as my example above, but hopefully that gives a basic understanding of the type of operations you may need to avoid.
I have problem integrating GDK Glassware and Mirror API Glassware as described here. I need to open GDK glassware application using Mirroe api Glassware app MenuItem. Can I send data bundle with intent. Does anybody have an idea about that.
Thank you.
I have finally figured out a way to do that
First add your custom scheme to android activity tag in AndroidManifest.xml
<activity
android:name="com.sanath.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="com.google.android.glass.action.VOICE_TRIGGER" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data android:scheme="com.sanath.scheme" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.google.android.glass.VoiceTrigger"
android:resource="#xml/vision_voice_trigger" />
</activity>
Then in Glassware timeline MenuItem add like following
new MenuItem(){
Action = "OPEN_URI",
Payload = "com.sanath.scheme://open/Welcome/2014",
Values = new MenuValue[]
{
new MenuValue()
{
DisplayName = "Open",
State = "DEFAULT"
},
new MenuValue()
{
DisplayName = "Launching",
State = "PENDING"
},
new MenuValue()
{
DisplayName = "Launched",
State = "CONFIRMED"
},
},
},
}
Then inside your Activity OnCreate method you can get data as following
Uri data = getIntent().getData();
List params = data.getPathSegments();
String param0 = params.get(0); // "welcome"
String param1 = params.get(1); //"2014"
String welcomeMsg = param0+" to "+param1;
/*show time line card
* */
Card welcomeCard =new Card(this);
welcomeCard.setText(welcomeMsg);
welcomeCard.setFootnote(param1);
View view =welcomeCard.toView();
setContentView(view);
Hope this will help others
It is not possible to provide data through bundle, but you can use query parameters or hash fragment in your URI to provide the necessary data.
Example:
myscheme://<SOME_PATH>?param1=value1¶m2&value2
Then, in your GDK Glassware, simply parse the query parameters and process their values.
I want to create different product views based on the attribute set the product belongs to:
does Magento provide a way to do this?
- UPDATE -
Following dan.codes suggestion I've added
$update->addHandle('PRODUCT_ATTRIBUTE_SET_ID_'.$product->getAttributeSetId());
to Mage_Catalog_ProductController (I duplicated ProductController.php and put it in local/Mage/Catalog/controllers/).
Then I added this to catalog.xml
<PRODUCT_ATTRIBUTE_SET_ID_9> // PRODUCT ID of Book Attribute Set
<label>Catalog Product View (Book)</label>
<reference name="product.info">
<block type="catalog/product_view_type_book" name="product.info.book" as="product_type_data" template="catalog/product/view/attribute_set/book.phtml">
<block type="core/text_list" name="product.info.book.extra" as="product_type_data_extra"/>
</block>
</reference>
</PRODUCT_ATTRIBUTE_SET_ID_9>
just after
<PRODUCT_TYPE_virtual translate="label" module="catalog">
<label>Catalog Product View (Virtual)</label>
<reference name="product.info">
<block type="catalog/product_view_type_virtual" name="product.info.virtual" as="product_type_data" template="catalog/product/view/type/virtual.phtml">
<block type="core/text_list" name="product.info.virtual.extra" as="product_type_data_extra"/>
</block>
</reference>
</PRODUCT_TYPE_virtual>
I then created catalog/product/view/attribute_set/book.phtml, but it is not displayed in my product view page.
- UPDATE MAGENTO 1.5 -
I've noticed that the handler update has moved in the last Magento release.
$update->addHandle('PRODUCT_TYPE_'.$product->getTypeId());
$update->addHandle('PRODUCT_'.$product->getId());
is in Mage/Catalog/Helper/Product/View.php now.
I've tested and it still works great!
No it doesn't but you can extend the functionality to do so by extending the _initProductLayout method in Mage_Catalog_ProductController under where the code is this
$update = $this->getLayout()->getUpdate();
$update->addHandle('default');
$this->addActionLayoutHandles();
$update->addHandle('PRODUCT_TYPE_'.$product->getTypeId());
$update->addHandle('PRODUCT_'.$product->getId());
You could add
$update->addHandle('PRODUCT_ATTRIBUTE_SET_ID_'.$product->getAttributeSetId());
Then in your layout.xml you could have
<PRODUCT_ATTRIBUTE_SET_ID_IDHERE>
<reference name="root">
<action method="setTemplate"><template>template/path/here.html</template></action>
</reference>
</PRODUCT_ATTRIBUTE_SET_ID_IDHERE>
If in case you want to switch view.phtml based on the attribute set then here is what you need to do:
<PRODUCT_ATTRIBUTE_SET_ID_9>
<label>Catalog Product View (Default)</label>
<reference name="product.info">
<action method="setTemplate"><template>catalog/product/custom-view.phtml</template></action>
</reference>
</PRODUCT_ATTRIBUTE_SET_ID_9>
Just add this in your catalog.xml or local.xml
Hope this helps.
Thanks
There is a good tutorial on this: http://magebase.com/magento-tutorials/creating-custom-layout-handles/
This uses following event: controller_action_layout_load_before
For this I set up in config.xml following
<events>
<controller_action_layout_load_before>
<observers>
<mymodule>
<class>mymodule/observer</class>
<method>addAttributeSetHandle</method>
</mymodule>
</observers>
</controller_action_layout_load_before>
</events>
And in Observer.php I will have
public function addAttributeSetHandle(Varien_Event_Observer $observer)
{
$product = Mage::registry('current_product');
/**
* Return if it is not product page
*/
if (!$this->isBookProduct($product)) {
return;
}
$niceName = 'book';
/* #var $update Mage_Core_Model_Layout_Update */
$update = $observer
->getEvent()
->getLayout()
->getUpdate();
$handles = $update->getHandles(); // Store all handles in a variable
$update->resetHandles(); // Remove all handles
/**
* Rearrange layout handles to ensure PRODUCT_<product_id>
* handle is added last
*/
foreach ($handles as $handle) {
$update->addHandle($handle);
if ($handle == 'PRODUCT_TYPE_' . $product->getTypeId()) {
$update->addHandle('PRODUCT_ATTRIBUTE_SET_' . $niceName);
}
}
}
protected function isBookProduct($product)
{
if (null === $product || !($product instanceof Mage_Catalog_Model_Product)) {
return false;
}
// TODO instead of hardcoded value we could use here something neat to get by name thru eav/entity_attribute_set model, some config value which hold that ID or use some other approach...
$book_set_id = 9;
if ($product->getAttributeSetId() != $book_set_id) {
return false;
}
return true;
}
This makes possibility to use in layout xml following:
<?xml version="1.0"?>
<layout version="0.1.0">
<PRODUCT_ATTRIBUTE_SET_book>
<reference name="product.info">
<action method="setTemplate">
<template>mymodule/book/product/view.phtml</template>
</action>
</reference>
</PRODUCT_ATTRIBUTE_SET_book>
</layout>