Blogger

  • This email address is being protected from spambots. You need JavaScript enabled to view it.

    Recent items

Login

Luca Costante

Luca Costante

In the last period, This email address is being protected from spambots. You need JavaScript enabled to view it. and I are working hard with AirWarch environment (in special case AirWatch Browser) and our applications based on SharePoint 2013.

One of the most important (and dangerous) issue is related to the javascript Cross Domain (if you don't know what it's, I''m suggesting you to read this article).

We had a lot of applications that get data, manipulate it and forwarded to other applications from other applications. Unfortunately, all of these applications has their own URLs and a lot of them are in different domains.

We started to analyze the issue finding a workaround that is not impacting our infrastructure too much. Following, the description of the workaround:

  • we created new URLs for the applications in cross domain area in order to have URLs in the form of subdomain. This is an example
    • imagine to have 2 applications: A with URL http://tetris.contoso.com and application B with http://pacman.contoso.com. If from application A you try to call a WebService or another service via ajax (javascript), AirWach Browser will block it to avoid the issue of cross domain (for security reason)
  • our idea  (and the solution is):
    • create for application B an additional URL like http://pacman.tetris.contoso.com.
    • On IIS we added to the bindings of the web application the new URL
    • checked if the application is adding to the response the header "Access-Control-Allow-Origin". We did not have it, so to have it, we created the Global.asax object and into the Global.asax.cs class we added the following code

Show/Hidden csharp code

View source
 
 
 
protected void Application_BeginRequest(object sender, EventArgs e)
{
    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin" , "*");
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
        HttpContext.Current.Response.End();
    }
}
 
 
 

Magically, everything started to work fine. With this approach, we are now able to allow applications to communicate each other.

Working with anonymous zone in SharePoint is every time very hard to work.

First of all you need to:

  • enable it into the web application with a specific zone
    • Navigate to SharePoint 2010 Central Administration -> Application management -> Manage web applications.
    • Choose the web application you would like to configure and click on Authentication Providers
    • Click on the zone that you would configure
    • On the Edit Authentication screen choose the Enable anonymous access option and click on save.
  • use the URL of the configured zone to enable the anonymous
    1. Our next step is to open your SharePoint site -> Site Actions -> Site Permissions
    2. Specify which parts of your web site you would like to enable anonymous access for and click on OK (Entire web site is suggested)
    3. Navigate to Galleries -> Master Pages and page layouts
    4. Click on the library tab
    5. Click on Library Permissions
    6. Click on Anonymous Access
    7. Specify the permission level of anonymous users. In our case we would like anonymous users to be able to view items.
    8. Navigate to Site Actions –> View All Site Content
    9. Click on Style Library and repeat the actions in steps 4 – 8.
  • Now is the time to test. Close the browser and re-open it (is suggested to use a Chrome of Firefox browser for these test to not allow Internet Explorer to send automatically the credentials if configured). If we see the ” Sign In” button on the top of the screen that means our configuration is correct and we can access the site anonymously.

It worked for us for a long time but a particular day, it stopped to work. The users started to receive 401 error (access denied).

We started the analysis and we:

  • checked the configuration in another web application and it worked
  • checked the file web.config and it was correctly filled
  • parsed GBs and GBs of logs to find out the issue

After long days we found out the issue: the reason was a user policy which denied access on the web application for one user account on all zones. After removing this policy from the zone providing the anonymous access eveything is working as expected.

I hope that this solution can help someone else :)

Friday, 25 September 2015 09:40

ContentDataBase deletion error

Hi,

if you're trying to remove a ContentDataBase following these steps

  • Remove the ContentDataBase from the Central Administration
  • Inside SQL, the DB is not removed. If you try to delete it (right click on the DB name and click on delete button) yuo will receive a SQL error (615 in my case)

and not works, try to execute the following SQL Commands, it works for me

Show/Hidden sql code

View source
 
 
 
USE master
 
 
GO
 
 
ALTER DATABASE [databasename]
 
 
SET OFFLINE WITH ROLLBACK IMMEDIATE
 
 
GO
 
 ALTER DATABASE [databasename] SET emergency 
 
 
DROP DATABASE [databasename]
 

 

Friday, 25 September 2015 07:56

Error during Restore-SPSite

Good morning,

I would describe a strange situation (never appeared before).

I was in a situation where in my web applications there was a series of wrong actions with backup of the ContentDB and site collection. The idea is to clean the situation making a Backup-SPSite of the site colleciton that I need, remove all site collection not used or that are wrong, create a new one and restore the backup.

All seems to proceed correctly until i should execute Restore-SPSite command. I press enter and:

"Restore-SPSite : No content databases are available for this operation but the site collection is scheduled for deletion in at least one content database.  Either wait for the deletion operation to complete or create a content database, and then try the operation again. To create a content database, click "Content databases" on the Application Management page, select the Web application to use, and then click "Add a content database"."

After some searches, I found the solution:

  1. Get-SPDeletedSite (to view the list of the sitecollections that were not removed correctly)
  2. Remove-SPDeletedSite -Identity <GUID> (to remove the site collection listed with the previous command
  3. Get-SPDeletedSite (to check that everything is clean)
  4. Run Gradual Site Deletion Timer Job (waiting the ending)
  5. FINALLY: Restore with PS!

Recently, I faced a really thorny issue regarding the search engine of SharePoint 2013 . After moving some pages from into a folder, I've created a Content Search Web Part (CSWP) to display that pages. I don't know why but some search results are displayed as duplicate values.

An option to resolve the issue is to use the Search Results Web Part that is able to give matching results because the query builder gives a Remove Duplicates option in the Settings tab. Unfortunately, the CSWP does not give this option on its Settings tab. Moreover, the default settings for the CSWP is to trim the duplicated values. The setting is, however, actually available in the web part definition and to be sure of its configuration I've:

  • exported the web parts
  • found the string "TrimDuplicates". If the value is "true" it means that the CSWP should remove the duplicates, if "false" not (it’s the equivalent of the Remove Duplicates option in the Search Results web part)

So why are we still getting duplicates? Probably there is a bug on the CSWP. To understand better the problem, I found this blog where it is described the current scenario and there are more details.

At the end, to fix this issue through a workaround (worked for me), I've followed these steps:

  1. In the CSWP query builder, go to the Refiners tab
  2. Click the little “Show more” link at the bottom
  3. In the “Group By” dropdown, select “—Show all properties—“ and then select DocumentSignature
  4. Click on the "OK" button a save the page

 

You should now see the correct number of results with the CSWP.

 

 

 

In these days, me and This email address is being protected from spambots. You need JavaScript enabled to view it. had working on an easy requirement but that to realized it, we we thought too much.

What we need to realize it is a simple Item type refinement panel that works with a multiple selection, easy.

A first idea was to change the settings on the refinement from single selection to multiple selection. But it not produced what we expected:

  1. The label was changed from Type to extentions. Example: from Web Pages to html, etc.
  2. some items that were found they not had the respective item in the refinement panel and some associations were wrong: example the videos are grouped with the html filter, etc.

After some analysis phases, we were able to make these assumptions:

  • a lot of items were crawled with the dispform.aspx, so they were grouped as html. They had another Managed Property (MP) "SecondaryFileExtention" that contained the correct file extention of the item
  • Some items, for example the video, are managed from SharePoint with a particular Content Type (ContentTypeId=). These items appears in the search both FileType MP and SecondaryFileExtention MP empty
  • to complete the work, the File Type filter need to group on:
    • for some items on the FileType MP
    • for some items on the SecondaryFileExtention MP
    • for some items on the ContentType MP
  • The logic of the refinement panel is not able to apply OR rules (written by himself by the respective refinement panel display template) on different Managed Properties.

At the end of a long week of tests, we had the solution:

  • We created a new Managed Property with the name LC.ResultType that contains the follow crawled properties (all of the single MP)
    • ows_ContentTypeId
    • ows_FileType
    • ows_File_x0020_Type
  • After a full crawl to allow the Managed Property to be filled, we modified the OOB Multi Selection Display Template to point to our Custom Managed Property in each occurrences
  • We creted the follow mapping of the item types, save and publish the new Display Template

Custom Multi selection Display Template example that use the custom Managed Property LC..ResultType:

Show/Hidden sql code

View source
 
 
 
<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:A29FA29F-C1488-11d1-1010-C2F400AA002"> 
<head>
<title>Multi-value</title>
 
<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:CompatibleManagedProperties msdt:dt="string"></mso:CompatibleManagedProperties>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:CompatibleSearchDataTypes msdt:dt="string"></mso:CompatibleSearchDataTypes>
<mso:MasterPageDescription msdt:dt="string"></mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106604</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#Refinement;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>
<mso:CrawlerXSLFile msdt:dt="string"></mso:CrawlerXSLFile>
<mso:HtmlDesignPreviewUrl msdt:dt="string"></mso:HtmlDesignPreviewUrl>
<mso:HtmlDesignConversionSucceeded msdt:dt="string">True</mso:HtmlDesignConversionSucceeded>
<mso:HtmlDesignStatusAndPreview msdt:dt="string">http://SEARCH.lucacostante.com/_catalogs/masterpage/Display Templates/Filters/MultiValue_ResultType.html, Conversion successful.</mso:HtmlDesignStatusAndPreview>
</mso:CustomDocumentProperties></xml><![endif]-->
</head>
<body>
<div id="Filter_MultiValue">
<!--#_
    var Options = {
        ShowCounts: TRUE
    };
 
    var listData = ctx.ListData;
    var hasControl = !$isNull(ctx.RefinementControl) && !$isNull(ctx.ClientControl);
 
    IF(hasControl) {
        var hasNoListData = ($isEmptyArray(listData));
        var propertyName = ctx.RefinementControl.propertyName;
        var displayTitle = Srch.Refinement.getRefinementTitle(ctx.RefinementControl);
        var isExpanded = Srch.Refinement.getExpanded(ctx.RefinementControl.propertyName);
        var useContains = FALSE;
        var useKQL = FALSE;
        var refiners = [];
        var refinersAll = [];
        
        IF (hasNoListData) {
            listData = [];
        }
        
        // TODO: unify same FileType
        listData = mapResultType(listData);
        
        IF (ctx.RefinementControl.csr_filters) {
            FOR(var t = 0; t < ctx.RefinementControl.csr_filters.LENGTH; t++) {
                refinersAll.push({
                    PropertyName: ctx.RefinementControl.csr_filters[t].PropertyName,
                    RefinementName: ctx.RefinementControl.csr_filters[t].RefinementName,
                    RefinementTokens: ctx.RefinementControl.csr_filters[t].RefinementTokens,
                    RefinementTokensMap: ctx.RefinementControl.csr_filters[t].RefinementTokensMap,
                    RefinementCount: ctx.RefinementControl.csr_filters[t].RefinementCount,
                    IsSelected: FALSE
                });
            }
        }
 
        var currentRefinementCategory = ctx.ClientControl.getCurrentRefinementCategory(ctx.RefinementControl.propertyName);
        var hasAnyFilterTokens = (!$isNull(currentRefinementCategory) && currentRefinementCategory.get_tokenCount() > 0);
        var renderEmptyContainer = hasControl && (hasNoListData && !hasAnyFilterTokens);
        
        IF(!renderEmptyContainer) {
            var listDataTokenToDisplayMap = {};
            var listDataTokenToCountMap = {};
            IF(!hasNoListData) {
                FOR (var i = 0; i < listData.LENGTH; i++) {
                    var FILTER = listData[i];
                    IF(!$isNull(FILTER)) {
                        FOR (var j = 0; j < FILTER.RefinementTokens.LENGTH; j++) {
                            listDataTokenToDisplayMap[FILTER.RefinementTokens[j]] = FILTER.RefinementName;
                            listDataTokenToCountMap[FILTER.RefinementTokens[j]] = FILTER.RefinementCount;
                        }
                        
                        IF(!hasAnyFilterTokens && !$isEmptyString(FILTER.RefinementName) && !$isEmptyString(FILTER.RefinementTokens)) {
                            refiners.push(
                            {
                                PropertyName: FILTER.RefinerName,
                                RefinementName: FILTER.RefinementName,
                                RefinementTokens: FILTER.RefinementTokens,
                                RefinementTokensMap: FILTER.RefinementTokensMap,
                                RefinementCount: FILTER.RefinementCount,
                                IsSelected: FALSE
                            });
                        }
                    }
                }
            }
            
            IF(hasAnyFilterTokens) {
                FOR(var j = 0; j < currentRefinementCategory.get_tokenCount(); j++) {
                    var token = currentRefinementCategory.t[j];
                    var displayValue = listDataTokenToDisplayMap[token];
                    IF($isEmptyString(displayValue) && !$isNull(currentRefinementCategory.m)) {
                        displayValue = currentRefinementCategory.m[token];
                    }
                    IF(!$isEmptyString(displayValue) && !$isEmptyString(token)) {
                        IF (refinersAll.LENGTH > 0) {
                            FOR (var k = 0; k < refinersAll.LENGTH; k++) {
                                FOR (var t = 0; t < refinersAll[k].RefinementTokens.LENGTH; t++) {
                                    IF (refinersAll[k].RefinementTokens[t] == token) {
                                        refinersAll[k].IsSelected = TRUE;
                                        break;
                                    }
                                }
                            }
                        }
                        ELSE {
                            refiners.push(
                            {  
                                PropertyName: FILTER.RefinerName,
                                RefinementName: displayValue,
                                RefinementTokens: token,
                                RefinementCount: !$isNull(listDataTokenToCountMap[token]) ? listDataTokenToCountMap[token] : 0,
                                IsSelected: TRUE
                            });
                        }
                    }
                }
            }
        }
        
        ctx.RefinementControl["csr_propertyName"] = propertyName;
        ctx.RefinementControl["csr_displayTitle"] = displayTitle;
        //ctx.RefinementControl["csr_filters"] = refiners;
        ctx.RefinementControl["csr_filters"] = hasAnyFilterTokens && refinersAll.LENGTH > 0 ? refinersAll : refiners;
        ctx.RefinementControl["csr_isExpanded"] = isExpanded;
        ctx.RefinementControl["csr_renderEmptyContainer"] = renderEmptyContainer;
        ctx.RefinementControl["csr_useContains"] = useContains;
        ctx.RefinementControl["csr_useKQL"] = useKQL;
        ctx.RefinementControl["csr_showCounts"] = Options.ShowCounts;
 
        // SHOW Item
        renderRefinerItems(ctx);
    }
_#-->
 
<!--#_
 
    FUNCTION mapResultType(listData) {
        var map = { };
        // Standard ResultType...
        map[Srch.U.loadResource("rf_ResultTypeRefinerValue_MSPowerPoint")] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["ppt", "pptx", "pps", "ppsx", "odp", "pptm", "potm", "potx", "ppam", "ppsm"]
        };
        map[Srch.U.loadResource("rf_ResultTypeRefinerValue_MSWord")] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["docx", "doc", "dot", "rtf", "txt", "docm", "nws", "dotx"]
        };
        map[Srch.U.loadResource("rf_ResultTypeRefinerValue_MSExcel")] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["xls", "xlsx", "csv", "odc", "ods", "xlsb", "xlsm", "xltm", "xltx", "xlam"]
        }; 
        map[Srch.U.loadResource("rf_ResultTypeRefinerValue_AdobePDF")] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["pdf"]
        };
        map[Srch.U.loadResource("rf_ResultTypeRefinerValue_Video")] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["0x0120D520A8*", "wmv", "avi", "flv", "mov", "mpeg"]
        };
        map["Audio File"] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["mp4", "mp3", "wma", "ra", "Podcast"]
        };
        map[Srch.U.loadResource("rf_ResultTypeRefinerValue_Archive")] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["zip", "rar"]
        };
        map[Srch.U.loadResource("rf_ResultTypeRefinerValue_Webpage")] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["HTML", "xml", "MHTML"]
        };
 
 
 
        // Specific ResultType 
        map["News"] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF390039E7E22DFD724B12B47BFBC3F5AA086D000580873f397b481ab8c1115a1cfc37a8*", "0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF390039E7E22DFD724B12B47BFBC3F5AA086D000580873F397B481AB8C1115A1CFC37A800a3b3a6c651184e438510779fe223a2a6*"]
        };
        map["Tool"] ={
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["0x01000268E795EAEA4ABB8E5C2E8D0AB2485C*"]
        };
        map["PhotoGallery"] = {
            "RefinerName": "LC.ResultType",
            "RefinementValues": ["0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF390039e7e22dfd724b12b47bfbc3f5aa086d00b1d929c83a1a4f37ae818af558a4898200116ce8a6eddf43c9af19c678407d4166*"]
        };
        
        var retListData = NEW Array();
        var assocListData = NEW Array();
        FOR (var i = 0; i < listData.LENGTH; i++) {
            var FILTER = listData[i];
            var mappedRefinementName = NULL;
            FOR(var KEY IN map) {
                IF (map[KEY].RefinerName == FILTER.RefinerName) {
                    FOR (var j = 0; j < map[KEY].RefinementValues.LENGTH; j++) {
                        var actualValue = FILTER.RefinementValue.toLowerCase();
                        var candidateValue = map[KEY].RefinementValues[j].toLowerCase();
 
                        IF (actualValue == candidateValue ||
                            (actualValue.startsWith("0x") && actualValue.startsWith(candidateValue.SUBSTRING(0, candidateValue.LENGTH - 1))))
                        {
                            mappedRefinementName = KEY;
                            break;
                        }
                    }
                    IF (!$isNull(mappedRefinementName)) {
                        break;
                    }
                }
            }
 
            var mappedFilter = NEW Object();
            
            IF (!$isNull(mappedRefinementName)) {
                mappedFilter.RefinerName = map[mappedRefinementName].RefinerName;
                mappedFilter.RefinementCount = FILTER.RefinementCount;
                mappedFilter.RefinementName = mappedRefinementName;
                mappedFilter.RefinementTokens = [];
                //var resultTypeTokenWrapper = (mappedFilter.RefinerName.toLowerCase() == "contenttypeid") ? FUNCTION (x) {RETURN x;} : 
                //                                                                                           Srch.RefinementUtil.stringValueToEqualsToken;
                var resultTypeTokenWrapper = FUNCTION(token) {
                    IF (token.startsWith("0x")) {
                        RETURN token;
                    }
                    
                    RETURN Srch.RefinementUtil.stringValueToEqualsToken(token);
                };
                FOR (var j IN map[mappedRefinementName].RefinementValues) {
                    mappedFilter.RefinementTokens.push(resultTypeTokenWrapper(map[mappedRefinementName].RefinementValues[j]));
                }
 
                IF ($isNull(assocListData[mappedFilter.RefinementName])) {
                    assocListData[mappedFilter.RefinementName] = mappedFilter;
                }
                ELSE {
                    assocListData[mappedFilter.RefinementName].RefinementCount += mappedFilter.RefinementCount;
                }
            }
        }
 
        FOR (var KEY IN assocListData) {
            retListData[retListData.LENGTH] = assocListData[KEY];
        }
 
        RETURN retListData;
    }
_#-->
 
<!--#_
    AddPostRenderCallback(ctx, FUNCTION() {
        $('#Container input[type=checkbox]').ON('click', FUNCTION() {
            IF ($(this).IS(':checked')) {
                $(this).parent().find('label').css("font-weight", "bold").css("color", "#2D2D2D");
            } ELSE {
                $(this).parent().find('label').css("font-weight", "").css("color", "");
            }
        });
    });
_#-->
 
<!--#_
    FUNCTION renderRefinerItems(ctx) {
        var propertyName = ctx.RefinementControl["csr_propertyName"];
        var displayTitle = ctx.RefinementControl["csr_displayTitle"];
        var filters = ctx.RefinementControl["csr_filters"];
        var isExpanded = BOOLEAN(ctx.RefinementControl["csr_isExpanded"]);
        var renderEmptyContainer = BOOLEAN(ctx.RefinementControl["csr_renderEmptyContainer"]);
        var useContains = BOOLEAN(ctx.RefinementControl["csr_useContains"]);
        var useKQL = BOOLEAN(ctx.RefinementControl["csr_useKQL"]);
        var showCounts = BOOLEAN(ctx.RefinementControl["csr_showCounts"]);
 
        IF($isEmptyString(propertyName) || (!$isNull(renderEmptyContainer) && renderEmptyContainer)) { 
_#-->
            <div id="EmptyContainer"></div>
<!--#_
        }
        ELSE IF(!$isNull(filters) && Srch.U.isArray(filters) && !$isEmptyArray(filters)) { 
            var expandedStatus = !$isNull(isExpanded) ? isExpanded : TRUE;
            var iconClass = "ms-core-listMenu-item ";
 
            iconClass += expandedStatus ? " ms-ref-uparrow " : " ms-ref-downarrow ";
_#-->
            <div id="_#= propertyName =#_-MultiRefiner">
            <div id="Container">
                _#= Srch.U.collapsibleRefinerTitle(propertyName, ctx.ClientControl.get_id(), displayTitle, iconClass) =#_
                <div class="ms-ref-unselSec" id="UnselectedSection">
                    <div id="unselShortList" class="ms-ref-unsel-shortList">
<!--#_ 
            FOR (var i = 0; i < filters.LENGTH; i++) {
                var FILTER = filters[i];
                IF(!$isNull(FILTER)) {
                    var inputValues = "";
                    var isSelected = BOOLEAN(FILTER.IsSelected);
                    var inputName = propertyName + '_ChkGroup';
                    var inputId = inputName + "_" + FILTER.RefinementName;
                    var nameClass = "ms-ref-name " + (showCounts ? "ms-displayInline" : "ms-displayInlineBlock ms-ref-ellipsis");
                    var selectClass = " custom-ref-fullwidth " + ((i == (filters.LENGTH - 1)) ? "" : " bordered-bottom ") + (isSelected ? " bold-text " : "");
                    
                    IF (FILTER.RefinementTokensMap) {
                        // multi typed refinement CASE
                        FOR(var KEY IN FILTER.RefinementTokensMap) {
                            inputValues += KEY + ":" + FILTER.RefinementTokensMap[KEY] + "|";
                        }
                    }
                    ELSE {
                        inputValues = FILTER.RefinementTokens;
                    }
_#-->
                        <div id="Value" class="_#= selectClass =#_">
<!--#_
                    IF(isSelected) {
_#-->
                            <div class="cust-filter-ck">
                                <INPUT TYPE="checkbox" class="ms-padding0 ms-margin0 ms-verticalAlignMiddle" id="_#= $htmlEncode(inputId) =#_" name="_#= $htmlEncode(inputName) =#_" data-displayValue="_#= $htmlEncode(filter.RefinementName) =#_" VALUE="_#= $htmlEncode(inputValues) =#_" checked="" onclick="MultiRefinement.SubmitRefinement('_#= $scriptEncode(filter.PropertyName) =#_', $getClientControl(this), '_#= $scriptEncode(inputId) =#_', _#= isSelected =#_);" />
                            </div>
<!--#_
                    } ELSE {
_#-->
                            <div class="cust-filter-ck">
                                <INPUT TYPE="checkbox" class="ms-padding0 ms-margin0 ms-verticalAlignMiddle" id="_#= $htmlEncode(inputId) =#_" name="_#= $htmlEncode(inputName) =#_" data-displayValue="_#= $htmlEncode(filter.RefinementName) =#_" VALUE="_#= $htmlEncode(inputValues) =#_" onclick="MultiRefinement.SubmitRefinement('_#= $scriptEncode(filter.PropertyName) =#_', $getClientControl(this), '_#= $scriptEncode(inputId) =#_', _#= isSelected =#_);" />
                            </div>
<!--#_
                    }
_#-->
                            <label FOR="_#= $htmlEncode(inputId) =#_" class='_#= nameClass =#_'>
                                _#= $htmlEncode(FILTER.RefinementName) =#_
                            </label>
<!--#_
                    IF (showCounts) {
_#-->
                            <label FOR="_#= $htmlEncode(inputId) =#_" class='_#= nameClass =#_ cust-ref-count'>
                                <span id='RefinementCount' class='ms-ref-count ms-textSmall'> (_#= $htmlEncode(Srch.U.toFormattedNumber(FILTER.RefinementCount)) =#_) </span>
                            </label>
<!--#_
                    }
_#-->
                        </div>
<!--#_
                }
            }
_#-->
                    </div>
                </div>
<!--#_
        }
_#-->
            </div>
            </div>
<!--#_
    }
_#-->
</div>
</body>
</html>
 
 
 
 
 

Results:

How expected, now we have a custom refiner that is able to filter on two property (in this case, but you can also add more property): the extention and the content type.

 

 

Hi everybody,

today I'm encourring in a strange problem: I need to display a value of a custom Managed Property inside the "Item_CommonItem_Body.html" Display Template, near the date visualization.

Here a little image regarding the result that I need (inside the red box there is the value of my custom Managed Property).

To add this value, you need to manipulate the "Item_CommonItem_Body.html" Display Template. How we know, to view the custom managed property, we need to declare it on top of the page and after we need to update the respective result type. So I go inside the result type page and I'm not able to see a result type that follow the "Item_CommonItem_Body.html" Display Template.

I've created a new result type that link to the Common Item Body, but when I reload the page, all items displayed are corrupted, the html il broken. Infact, all items had the id with undefined value and all not works fine.

At that time, the question was: how I can use it?

The solution is: you need to add the custom Managed Metadata definition inside the "Item_WebPage.html" Display template. After that, when you return inside the result type page, you need to copy the current one that contains the "Item_WebPage.html" display template. The system propones to update it.

Now the system is able to manage that values. So, now you can add the code to display the value inside the "Item_CommonItem_Body.html" Display template.

At the end of the history, to manage a custom Managed property inside the "Item_CommonItem_Body.html" display template, you need:

  1. Define the Managed Metadata property inside the "Item_WebPage.html" display template
  2. Create and update a result type based on "Item_WebPage.html"
  3. Use you custom managed metadata property inside the "Item_CommonItem_Body.html"

Note: if you don't want problems with a wrong displaying of the results, you mustn't never create a result type that use the "Item_CommonItem_Body.html".

I would to share with the network the snippet code to enable the Scheduling settings via Client SharePoint Object Model APIs.

This first block provide to enable the Scheduling on all pages list of the site collection

Show/Hidden csharp code

View source
 
 
 
 public void EnablePagesSchedulingOnAllSiteCollection(CustomWebApplication wa)
        {
            try
            {
                foreach (CustomSiteCollection sc in wa.SiteCollections)
                {
                    using (ClientContext context = new ClientContext(wa.Url + sc.Url))
                    {
                        context.Credentials = new NetworkCredential(wa.UserName, wa.UserPassword, wa.UserDomain);
                        context.Load(context.Site.RootWeb, w => w.Webs, w => w.ServerRelativeUrl);
                        context.ExecuteQuery();
 
                        PageHelper.EnableScheduling(context, context.Site.RootWeb, true,sc.LanguageShortCode,logFilePath);
 
 
                    }
                }
            }
            catch (Exception ex)
            {
                string message = string.Format("------------- Exception EnablePagesSchedulingOnAllSiteCollection: {0}", ex.Message);
                Logger.WriteLog(message, logFilePath);
            }
        }
 
 
 

 

The second block provide to enable the settings on the list page recursively

Show/Hidden csharp code

View source
 
 
 
using Microsoft.SharePoint;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Publishing;
using Microsoft.SharePoint.Publishing.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Client.Common.Helpers
{
    public class PageHelper
    {
 
        public static Guid StartDateGUID
        {
            get
            {
                return new Guid("51d39414-03dc-4bd0-b777-d3e20cb350f7");
            }
        }
 
        public static Guid EndDateGUID
        {
            get
            {
                return new Guid("a990e64f-faa3-49c1-aafa-885fda79de62");
            }
        }
 
        internal static string GetPageListName(string language)
        {
            string pagesListName = string.Empty;
            switch (language)
            {
                case "it": pagesListName = "Pagine"; break;
                default: pagesListName = "Pages"; break;
            }
            return pagesListName;
        }
 
        internal static void EnableScheduling(ClientContext context, Web currWeb, bool recursive, string language, string logFilePath)
        {
            try
            {
                List pages = ListHelper.GetList(context, currWeb, GetPageListName(language), logFilePath);
                EventReceiverDefinitionCollection eventReceivers = pages.EventReceivers;
 
 
                pages.EnableModeration = true;
                pages.EnableMinorVersions = true;
 
                pages.Update();
 
 
                //To enable Scheduling in the list
                string assembly = "Microsoft.SharePoint.Publishing, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c";
                string fullName = "Microsoft.SharePoint.Publishing.Internal.ScheduledItemEventReceiver";
 
                EventReceiverType typeItemUpdating = EventReceiverType.ItemUpdating;
                EventReceiverType typeItemAdded = EventReceiverType.ItemAdded;
                string itemUpdatingERName = "Item Updating Event Handler For Scheduling";
                string itemAddedERName = "Item Added Event Handler For Scheduling";
 
                bool foundUpdating = false;
                bool foundAddedd = false;
 
                foreach (EventReceiverDefinition e in eventReceivers)
                {
                    if (string.Compare(e.ReceiverName, itemUpdatingERName, true) == 0)
                        foundUpdating = true;
                    if (string.Compare(e.ReceiverName, itemAddedERName, true) == 0)
                        foundAddedd = true;
                }
 
                if (!foundUpdating)
                {
 
                    EventReceiverDefinitionCreationInformation erItemUpdating = new EventReceiverDefinitionCreationInformation();
                    erItemUpdating.ReceiverName = itemUpdatingERName;
                    erItemUpdating.EventType = typeItemUpdating;
                    erItemUpdating.ReceiverAssembly = assembly;
                    erItemUpdating.ReceiverClass = fullName;
 
                    eventReceivers.Add(erItemUpdating);
                }
 
                if (!foundAddedd)
                {
                    EventReceiverDefinitionCreationInformation erItemAdded = new EventReceiverDefinitionCreationInformation();
                    erItemAdded.ReceiverName = itemAddedERName;
                    erItemAdded.EventType = typeItemAdded;
                    erItemAdded.ReceiverAssembly = assembly;
                    erItemAdded.ReceiverClass = fullName;
 
                    eventReceivers.Add(erItemAdded);
                }
 
                List<FieldLinkCreationInformation> fieldsToAdd = new List<FieldLinkCreationInformation>();
                fieldsToAdd.Add(new FieldLinkCreationInformation() { Field = context.Site.RootWeb.Fields.GetById(StartDateGUID) });
                fieldsToAdd.Add(new FieldLinkCreationInformation() { Field = context.Site.RootWeb.Fields.GetById(EndDateGUID) });
 
                context.Load(fieldsToAdd[0].Field, f => f.Id);
                context.Load(fieldsToAdd[1].Field, f => f.Id);
 
                context.ExecuteQuery();
 
 
                foreach (FieldLinkCreationInformation f in fieldsToAdd)
                {
                    if (pages.Fields.Where(c => c.Id == f.Field.Id).Count() == 0)
                        pages.Fields.Add(f.Field);
                    else
                    {
                        pages.Fields.Where(c => c.Id == f.Field.Id).FirstOrDefault().Hidden = false;
                        pages.Fields.Where(c => c.Id == f.Field.Id).FirstOrDefault().Update();
                    }
                }
 
                context.ExecuteQuery();
 
                foreach (ContentType ct in pages.ContentTypes)
                {
                    try
                    {
                        context.Load(ct, c => c.FieldLinks, c => c.Fields, c => c.Name);
                        context.ExecuteQuery();
 
                        foreach (FieldLinkCreationInformation f in fieldsToAdd)
                        {
 
                            if (ct.FieldLinks.Where(c => c.Id == f.Field.Id).Count() == 0)
                                ct.FieldLinks.Add(f);
                            else
                                ct.FieldLinks.Where(c => c.Id == f.Field.Id).FirstOrDefault().Hidden = false;
 
                            if (ct.Fields.Where(c => c.Id == f.Field.Id).Count() == 0)
                                ct.Fields.Add(f.Field);
                            else
                                ct.Fields.Where(c => c.Id == f.Field.Id).FirstOrDefault().Hidden = false;
                        }
                        ct.Update(true);
                    }
                    catch (Exception ex)
                    {
                        Logger.WriteLog(string.Format("Error on CT {0}: {1} ", ct.Name, ex.Message), logFilePath);
                    }
                }
 
 
                if (!pages.DefaultView.ViewFields.Contains("Scheduling Start Date"))
                {
                    pages.DefaultView.ViewFields.Add("Scheduling Start Date");
                }
 
                if (!pages.DefaultView.ViewFields.Contains("Scheduling End Date"))
                {
                    pages.DefaultView.ViewFields.Add("Scheduling End Date");
                }
 
                pages.DefaultView.Update();
                pages.Update();
                context.ExecuteQuery();
 
                Logger.WriteLog(string.Format("Publishing enabled on list Pages of site {0}.", currWeb.ServerRelativeUrl), logFilePath);
 
                if (recursive)
                {
                    context.Load(currWeb, w => w.Webs);
                    context.ExecuteQuery();
 
                    foreach (Web subWeb in currWeb.Webs)
                    {
                        EnableScheduling(context, subWeb, recursive, language, logFilePath);
                    }
                }
 
            }
            catch (Exception ex)
            {
                Logger.WriteLog(string.Format("Error during EnableScheduling on web {0}: {1}", currWeb.ServerRelativeUrl, ex), logFilePath);
            }
        }
    }
}
 

Today I'm working with a particular error: when I search items that contains the single quote character through the REST API, I receive a bad request error (400 error).


The first steps is to analyze the response from the server:

  • Request: GET http://test.lucacostante.com/_api/search/query?querytext='path:http://test.lucacostante.com/Lists/Banners/Forms/AllItems.aspx OR path:http://test.lucacostante.com/Pages/L'universo.aspx'&rowlimit=5&selectproperties='Title,Path'
  • Response: Error 400: {"error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":{"lang":"en-US","value":"The expression \"'path:http://test.lucacostante.com/Lists/Banners/Forms/AllItems.aspx OR path:http://test.lucacostante.com/Pages/L'universo.aspx'\" is not valid."}}}

The problem is the single quote ' character into the query that provide to create a wrong query.

I've tried to encode the URL but this not resolve my problem. The solution is simpler: I need only to add another single quote to resolve my problem ('').

  • Request: GET http://test.lucacostante.com/_api/search/query?querytext='path:http://test.lucacostante.com/Lists/Banners/Forms/AllItems.aspx OR path:http://test.lucacostante.com/Pages/L''universo.aspx'&rowlimit=5&selectproperties='Title,Path'
  • Response: HTTP/1.1 200 OK

Today I've resolved a strange problem: when an user tries to copy a page from a folder to another one into the Pages library, the system provides to copy the page but if it contains some webparts, they will not be copied.

These are some assumptions:

  • if you have a web site based on Publishing site template, the copy page feature works fine
  • if you have only the major version versioning system on the Pages library the copy page feature doesn't work

The solution is that the copy page needs that on the Pages Library is enabled the versioning system with minor and major versioning. This allow also the copy of the webpart during the copy phase.

Page 1 of 5