Campaign Creator – Issue while creating and loading campaigns

Hi everyone,

Today I am here to share an issue which we faced while creating and loading campaigns.

We are using Sitecore 8.2 Update 3 instance and we started to use the Campaign Creator option, very recently and that’s when we noticed about these issues.

Here is the description of the issue :

When a user is trying to create a campaign from Campaign creator, we are getting the following error.
campaign 1

But the campaigns can be viewed from the Marketing Control panel.
campaign 2

When the campaign creator dashboard is loading in the startup, it must display the list of campaigns that are created and deployed. But it is showing ”No campaign activities found”.
campaign 3

In the logs, the following error was shown :

Exception System.ArgumentException: the definition was not found: {3288EF08-CC53-45E6-9804-29DD1B397695}
Parameter name: definitionId
at Sitecore.Diagnostics.Assert.ArgumentCondition(Boolean condition, String argumentName, String message)
at Sitecore.Marketing.Definitions.DefinitionManagerBase`1.<>c__DisplayClass5`1.<Activate>b__0()
at Sitecore.Marketing.Core.IgnoreRecursiveCalls.Run(ID id, Action action)
at Sitecore.Marketing.Definitions.DefinitionManagerBase`1.Activate[TRecord](ID definitionId, IDefinitionRepository`1 repository, Func`2 toDefinition)
at Sitecore.Marketing.Definitions.Campaigns.CampaignDefinitionManager.ActivateAsync(ID definitionId)
at Sitecore.Marketing.Definitions.DefinitionManagerBase`1.Save[TRecord](TDefinition definition, Boolean activate, IDefinitionRepository`1 repository, Action`2 setCustomFields)
at Sitecore.Marketing.Definitions.Campaigns.CampaignDefinitionManager.SaveAsync(ICampaignActivityDefinition definition, Boolean activate)
at Sitecore.Marketing.Definitions.DefinitionManagerBase`1.Save(TDefinition definition, Boolean activate)
at Sitecore.Marketing.Campaigns.Services.Data.CampaignRepository.Add(CampaignEntity entity)
at Sitecore.Services.Infrastructure.Services.EntityServiceBase`1.CreateEntity(T entity)
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
— End of stack trace from previous location where exception was thrown —
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()

We contacted Sitecore support for the issue, and after some analysis they got back to us with the following findings :

The issue was related to the fact that we were using Publishing Service module (2.0) in our instance. And also it is specified in the installation guide of the Sitecore Publishing Service that, the “content availability” feature must be turned off in CM server and should be turned on only on CD.

https://dev.sitecore.net/~/media/6A0A9E06FBD549059473643F4ADE19DB.ashx

The “Sitecore.Publishing.Service.Delivery.ContentSearch.ApplyGlobalAvailabilityLinqFilters, Sitecore.Publishing.Service.Delivery” processor from the “Sitecore.Publishing.Service.ContentAvailability.config” file breaks search on CM server and causes Campaign Creator to show empty dashboard page. Also the issue with the saving new campaign activity, is also related to the “content availability” feature and is caused by “filterItems” and “enableWorkflow” settings enabled in Sitecore.Publishing.Service.ContentAvailability.config configuration file.

We had enabled this feature that the CM server also should act as CD server for the content availablity for some purpose.

Campaign_Contentavailability

But as Sitecore suggested we disabled the “content availability” feature from the CM servers and BINGO!!! Both the issues which we mentioned were solved. Now we were able to create new campaigns and also see them in the dashboard.
But now, when the campaign dashboard was loading, it was showing only the newly created campaigns. But there were some default campaigns (Ex : Social) that are present in Sitecore and also some campaigns that are already created through our Marketing Control Panel under a folder , which were not getting displayed in the Campaign list. For solving this issue we have performed a rebuild of “sitecore_marketingdefinitions_master” and now all the campaigns are shown including the default ones.

rebuild marketing definitions

This was an implementation issue which occurred from our side, where we did not disable the “content availability” feature from the CM servers. I guess many other people also usually faces these kind of implementing issues and the main aim of this post was to notify everyone to implement the features/modules in Sitecore as per the installation guide and make sure that you disable/enable the configs listed as per the installation guide/Config Enable Disable Excel spreadsheet in both CM and CD servers.

Hope you enjoyed this post.

Will meet you all soom with a new issue or implementation.

Till then Bye. Happy Sitecoring!!!

Advertisements

Querying Sitecore Forms DB – Sitecore xDB Mongo Database

Hi all,

Welcome to my post on Querying Sitecore Forms collection in the xDB – Mongo Database.

MongoDB collection database is an important part of a Sitecore Experience Database (xDB) that allows the companies/organizations to collect all of their customer interactions/data from all channels that allows marketers to better optimize the customer experience in real-time. In xDB, the collection database acts as a central repository for storing contact, device, interaction, history and automation data.

Suppose we have created a form using WFFM and a user is submitting the form. If the form is submitted successfully, the Form Reports can be accessed from the “Form Reports” tab, when we click on a form in Sitecore. The same data is also saved in the MongoDB collection named “FormData” under the analytics database.

Screenshot 1

We all might face an issue with the the form that the email messages received is not same as the data shown in the Form Reports. For example, if there is an event form, and the event coordinator gets 50 emails as registered and when they check the form reports it shows only 45. Unless we go to the database directly and check the data, we are not able to confirm the issue. Also if we need to confirm whether a particular email id value is saved in the database.

So we can check some examples on how to query the MongoDB database using 2 tools : Robo 3T and Studio 3T (both are tools provided by formerly used tool Robomongo)

You can download the tool from https://robomongo.org/

Robo3T is used just by the MongoDB enthusiasists, who are interested just in querying the database and playing around the data using differnt queries.
Studio 3T is used mainly by the professionals and it provides following advantages :
1. Fully featured IDE with embedded shell
2. Visual Query Builder
3. In-Place editing
4. IntelliShell with Auto-Completion
5. Query MongoDB with SQL
6. Export to / import from SQL DB
7. Export to csv

There are three encoding supported for Legacy UUID subtype 3:

Legacy Java Encoding, Legacy .NET Encoding, Legacy Python Encoding

By default, when we open a collection, it opens the Raw data without any encoding. For understanding and easy querying, we use .NET encoding. We can select .NET encoding (in Robo 3T) by Navigating to Options -> Legacy UUID Encoding -> Use .NET Encoding

Screenshot 2

Now i will get on to how we can query the FormData. For that first we need to take the ID of the form where the issue is getting reflected.

The item ID of the form which we have used is {8E08E97B-0D58-4988-87CE-F5D354ECFC30}. This is the same ID which we use with querying with the NUUID.

1. To get all the records from the Form Data collection:

db.getCollection('FormData').find({"FormID":NUUID("8e08e97b-0d58-4988-87ce-f5d354ecfc30")})

This query gives the following results :

Screenshot 3

2. To get a particular value of any field of the form – Suppose i have a field called First Name and the value i have given is “Test”. Here is how we query it :

db.getCollection('FormData').find({"FormID":NUUID("8e08e97b-0d58-4988-87ce-f5d354ecfc30"),"Fields.Value":"Test"})

Screenshot 4

But here we get three different results which has the same Name : “Test”

3. Now lets choose an unique identifier (Email ID) so that i get a particular formdata which has FirstName as “Test” and Email ID as “test@test.com” . Here we get this using “AND” query.

db.getCollection('FormData').find({$and : [ {"FormID":NUUID("8e08e97b-0d58-4988-87ce-f5d354ecfc30")},{"Fields.Value":"test@test.com"}, {"Fields.Value":"Test"}]})

Screenshot 5

Here is the result when there is requirement to find whether the user with name “Test” and email ID “test@test.com” has submitted the form.

These were just very few examples on how to get forms data via querying through MongoDB. In similar way we can also query Interactions, Contact collections also to get more details on the Visitor data (Page count, Time, Browser, Site Name etc)
More details on the querying is provided in the series of blogs written by Brijesh Patel : https://horizontalintegration.blog/2017/01/22/query-sitecore-xdb-mongodatabases-part-1/

In my next blog, I will explain on how to query using Studio 3T, using Visual Query Builder, Importing the data to csv or excel. If you have any queries or doubts, please feel free to contact me.

Till then Bye Bye ! Happy Querying

Sitecore Powershell Extensions- Making work easier – Part 1

Hi all,

This time I am going to share a few powershell scripts that can be used for various requirements and reduce a big amount of time.

Before going on to those, first I would like to give some introduction about how I started scripting using SPE and how it helped me to proceed further.

So this was before 2 years, when I was working in a project and it was using Zen Garden, The first ever Sitecore Development Accelerator (Now Sitecore has stopped supporting the same and is discontinued) which had a similar properties as of Sitecore Experience Accelarator (SXA), which was used to created Multi-Sites using Tenants, Markets etc. So it was told that when we just right click on an item and select “Create a Tenant”, it showed some dialog boxes asking for templates, site name , language etc. and when given the necessary details, the site node was created immediately. There I was curious on how this is happening and after some research and debugging, I came to know that these all could be possible only because of Sitecore Powershell Extensions. There started my first step to SPE.

The Sitecore PowerShell module is especially handy when you’ve been tasked with applying changes to items in bulk. Then I started working on various scripts for different tasks that requires time saving and easy to be automated and was happy to know that it was working and still I am continuing my PowerShell scripting journey.

There are a large number of blogs for studying and implementing SPE. Of those i am suggesting following blogs to go through the basics of the same

https://marketplace.sitecore.net/en/Modules/Sitecore_PowerShell_console.aspx

https://doc.sitecorepowershell.com/

https://blog.najmanowicz.com/sitecore-powershell-console/

http://sitecore-masters.com/en/starting-with-sitecore-powershell/

Here I would like to share some scripts that can be handy on some occasions. Some of these scripts are also available in other websites also and these scripts might not be the only solution for the tasks but you could also try these scripts also as part of your investigation.

This blog post is heavily inspired from the posts and help provided by Adam Najmanowicz and Michael West on Sitecore PowerShell Extensions, through their blogs, Slack, Stack overflow etc. I have seen both of them working and helping really a lot for the people who are facing any difficulties in implementing the same. For joining the group which helps you to interact with Adam Najmanowicz and Michael West and more Powershell experts, please join the Sitecore Slack channel.

Now lets move on to the scripts one by one.

1. To change the template of all the child items

$path="Item path here"
$item = Get-ChildItem -path "$($path)"
$newTemplate = [Sitecore.Configuration.Factory]::GetDatabase("master").Templates["Template path here"];
$item | ForEach-Object {
    if($_.TemplateName -eq "TemplateName")
    {
        $_.ChangeTemplate($newTemplate)
    }
}
$item

2. To delete the sub item of all the child items of main item

$path="item path here"
$item = Get-ChildItem -path "$($path)" -Recurse
$item | ForEach-Object {
    if($_.TemplateName -eq "TemplateName")
    {
        Get-ChildItem $_.ProviderPath | Remove-Item
    }
}

3. Export the list of item under a particular item excluding a particular template to csv

$path="item path here"
$item = Get-ChildItem -path "$($path)" -Recurse | Where-Object { $_.TemplateName -ne "Template Name of items to be exported" }
 
$item | Show-ListView -Property `
    @{ Name="Item Name"; Expression={$_.DisplayName}}, # property renamed
    @{ Name="Item path"; Expression={$_.FullPath}}

4. To create items under an item from csv

$itempath = "item path here"
$templatePath = "template path here"
$InputcsvFile = Show-Input "Input file path"
$csv = Import-CSV $InputcsvFile -delimiter ","
 
$bulk = New-Object "Sitecore.Data.BulkUpdateContext"
try
{
	foreach($record in $csv)
	{
		$item = New-Item -Path $itempath -Name $record.ItemName -ItemType $templatePath
		$item.Editing.BeginEdit()
    		$item["__Display name"] = $record.ItemName 
   		$item.Editing.EndEdit()
		Write-Host "Item created: " $record.ItemName
	}
}
finally
{
 $bulk.Dispose()
}

5. To get all the links starting with ‘a’ tag in the items (from a richtext editor or single line text)

$itempath = "item path here"
$allItems = Get-ChildItem -Path $itempath -Recurse -language * -version *
$links = @() 
$allItems | ForEach-Object {
    foreach($field in $_.Fields) {
    # Only look within Single-line and Rich Text fields     
    if($field.Type -eq "Single-Line Text" -or $field.Type -eq "Rich Text") {
            $html = $field.Value
            $htmlDocument = New-Object -TypeName HtmlAgilityPack.HtmlDocument
            $htmlDocument.LoadHtml($html)
            foreach($x in $htmlDocument.DocumentNode.SelectNodes("//a")) {                
               $links +=@{Id=&{$_.id.toString()};Path=&{$_.paths.fullpath};Language=&{$_.language};Version=&{$_.version};Link=&{$x.OuterHtml}}                
            }
        }
    }
}
$links | Show-Listview -Prop Id,Path,Language,Version,Link

These were a few scripts which i think will be useful for someone who is curious to learn powershell and use them for reducing the amount of time in their projects.

Please feel free to contact me if any of you face any issues or having doubts in using the scripts.

I will continue with some new scripts in my upcoming blogs.
Till then, See you all. Happy Scripting …

“Forged request detected” exception – submitting WFFM form after period of activity

Hi all,

Today i am planning to share an issue which we faced in our webforms. I am using WFFM 8.2 Update 3.
The issue can be described as follows :

When a user starts filling a form which has more fields, he/she is filling some fields, and they are waiting for 25-30 mins for filling the rest of the fields, and clicks submit, the form will not get submitted and it displays an errorTechnical dificulty errorAt first we were thinking this issue might be because of the Mail service was not working, but when started investigating in the logs, we could not find any log error which corresponds to mail service.

But at the same time we received following in the logs :

5728 12:57:20 INFO AUDIT (extranet\Anonymous): Upload: example.pdf
5728 12:57:20 INFO Media Item has been uploaded to database: /{11111111-1111-1111-1111-111111111111}/{3D6658D8-A0BF-4E75-B3E2-D050FABCF4E1}/{25D39E8F-719B-4C95-9F43-A106C2C0EC54}/{338F9B9A-75A5-4304-A34B-A1F2F9B5F01C}/{CAA45999-AC9B-4F6F-89C6-B9F949030CDD}/{82D54811-0DA9-4CA8-B4A2-744C47321AD2}/example.pdf
5728 12:57:20 INFO AUDIT (extranet\Anonymous): [WFFM] Form {7100FF18-8969-48B0-833B-49C035C8A19C} is saving to db
5580 13:01:26 WARN [WFFM] Web Forms for Marketers: an exception: WFFM: Forged request detected! has occured while trying to execute an action.
5580 13:01:26 ERROR WFFM: Forged request detected!

In our further analysis we could find that this issue occurs when the session is expired.
Expiration is controlled by timeout value of the session state configuration in the web.config:

As described in the following blogspot : https://sitecoredoc.wordpress.com/2017/01/04/sitecore-wffm-v8-1-2-form-times-out-after-a-period-of-inactivity/, This is because of an anticsrf and the logic is simple. There is some value (guid) stored in the session and another value is on the form (hidden input control with “_anticsrf” postfix in id and name). If at the submission these values are different or session is null, this message about forged request will be logged and the submission will be aborted.
In my case, the session is expired in 20 minutes and session value at submission is null.

Possible workarounds :

1. Increase session timeout to 60 minutes.

2. There is a Sitecore support reference number for this : 456464, Please mention your WFFM version and this reference number to the Sitecore support.

3. We can temporarily bypass the forged request problem by adding some code logic for the same.
Create a class named ForgedRequestBypass.cs with following code

using System;
using Sitecore.Diagnostics;
using Sitecore.Form.Web.UI.Controls;

namespace YourNamespace
{
    /// <summary>
    /// This class is intended to be a temporary bypass for the forged request problem with the WFFM module.
    /// It's an implementation of #2 listed at https://community.sitecore.net/developers/f/10/t/3822.
    /// </summary>
    public class ForgedRequestBypass : SitecoreSimpleFormAscx
    {
        protected override void OnClick(object sender, EventArgs e)
        {
            Assert.ArgumentNotNull(sender, "sender");

            if (bool.Parse(Sitecore.Configuration.Settings.GetSetting("WFM.EnableAntiCsrf", "true")))
            {
                base.OnClick(sender, e);
            }
            else
            {
                object sessionValue = Sitecore.Form.Core.Utility.SessionUtil.GetSessionValue<object>(this.AntiCsrf.ID);

                if (sessionValue == null || !(sessionValue.ToString() == this.AntiCsrf.Value))
                {
                    Sitecore.Form.Core.Utility.SessionUtil.SetSessionValue(this.AntiCsrf.ID, this.AntiCsrf.Value);
                    Log.Info("Successfully Bypass forged request - Session value successfully stored",this);
                }

                base.OnClick(sender, e);
            }
        }
    }
}

Update the Control directive’s inherits attribute in the \Website\sitecore modules\Web\Web Forms for Marketers\control\SitecoreSimpleFormAscx.ascx file:

<%@ Control Language=”C#” AutoEventWireup=”true” CodeBehind=”SitecoreSimpleFormAscx.ascx.cs” Inherits=”YourNamespace.ForgedRequestBypass” %>

Also we need to create a patch for Sitecore.Forms.config and add the following setting to that

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
  <sitecore>
<!-- SETTING VALUE FOR ANTICSRF COOKIE-->
      <setting name="WFM.EnableAntiCsrf" value="false" /> 
    </settings>
  </sitecore>
</configuration>

After applying this fix, when you try to submit the same form even after the session is timed out, the form will be submitted successfully and you can see the following message in the logs.

5000 11:28:06 INFO Successfully Bypass forged request – Session value successfully stored
5000 11:28:06 INFO AUDIT (extranet\Anonymous): [WFFM] Form {7100FF18-8969-48B0-833B-49C035C8A19C} is saving to db

How i tested the issue : I changed the session timeout to 1 minute and then tried to submit form after 2-3 minutes, so before i applied the fix, it showed the error and after applying the fix, the form was submitted successfully.

And Finally the issue was solved !!!

I guess everyone liked my post. If anyone faces such type of issue and requires help please feel free to contact me. You are also welcome for any suggestions on the above post.

Happy Sitecoring !!!

ISSUES FACED IN SITECORE PROJECT

Hello everyone,

This time I am sharing some issue that we have faced in our project and the solution we had provided.

#1 : Media Items are served with extensions .ashx instead of .jpg, .pdf etc
By default media items(.jpg, .pdf, .xls etc) will be rendered as .ashx.
This can be handled from Media.requestExtension setting in Sitecore.config. By Default the value is

1

By setting the value to blank, we can render media url with relevant extension. We used custom patch for the setting

2

#2 : Sitecore Hyperlink manager/Mail template editor not clickable/broken
a) One morning we faced an issue that when we select hyperlink manager, a link builder dialogue opens, and the bottom of this dialogue has two small square. They look like small versions of buttons, but content is not there and are not clickable.
b) Similarly when we open mail template editor, to send email message through WFFM, The mail template editor opens, but:
* The content field of the template is blank
* It’s not possible to click the HTML button
* No values can be selected from the field dropdown
* If you start resizing the window it goes completely haywire with weird alert boxes

We could find that both of these are related to single issue. Because in the Console we were getting errors related to ScriptResource.axd.

This can be handled using the IgnoreURLPrefixes setting in Sitecore.config, adding script resource.axd.

3

After that, everything started working fine
(These two are the issues which we faced, there can be some other issues also due to unavailabilty of ScriptResource.axd in IgnoreURLPrefixes)

#3 : We have observed that there are multiple failed connections sparks on the Azure PaaS SQL DB causing application unavailability issue which looks transient error.

When we reached to Microsoft about this issue with the Error log for SQL DB, they replied that Reconfigurations happened in the databases.
Reconfiguration (briefly)
Reconfigurations are a common part of SQL Azure databases. Due to high availability architecture of Azure, its database has three replicas.Every time we need to point your application to a secondary replica, send an exception to the application so you can handle the error and resubmit the request to the database. These disconnections may occur during maintenance of database, or due to some error in the system, updating, patching the operating system, etc. Adding a retry logic to your code should help resolve these errors.

Reconfigurations generally occurs within 5-30 seconds for no impact to be seen, but application must reconnect to the healthy copy of the database. With an appropriate retry logic this would be transparent as the application could automatically connect as soon as the database is available. Below is more information on the connection recommendations for Azure SQL DB as well as retry logic configurations and suggestions.

So we enabled the retryer logic in Sitecore config file

By default it will be

4We had modified it to

8

#4 : Sitecore Media Library is very slow
The Sitecore Media Library is extremely slow at loading. The initial load is ok, but unfolding a main folder can take several minutes.

Based on the sitecore recommendation from the below blog

https://kb.sitecore.net/articles/723979

Set the value of the Media.MediaLinkPrefix setting in the Sitecore.config to the alternative prefix:

6

Add the following line to the customHandlers section (make sure NOT to remove the existing one that is mapped to “~/media”):7

Now the Media Library is loading better compared to previous.

These are some of the issues we faced in our Sitecore project. These might not be the Only solution for the same kind of issue. If you face such kind of issue, you could try these fixes also as part of your investigation. Please feel free to contact me if you have similar kind of issue or any doubts or you have any other solution.

TO GET BUILD DEFINITIONS USING VSTS API

Hello all,

It had been a long time since i have written my first blog post.

Here comes by second post on How to get build definitions through C# code.

Last month we had a requirement to see the build definitions and the corresponding build details on a page.

First step for that is create a personal token for authentication from your VSTS account. The details about this is given in
https://www.visualstudio.com/en-us/docs/setup-admin/team-services/use-personal-access-tokens-to-authenticate

As mentioned in the website, please copy the token and save it for yourself. It wont be available after that.

Create a .cs file for getting the build definitions

public void GetBuilds(int id, List myList)
 {
 try
 {
 var username = "/*Please enter the username for logging in VSTS*/";
 var password = "/*Please enter the token you received from VSTS*/";
 BuildValues values = new BuildValues(); 
 using (HttpClient client = new HttpClient())
 {
 client.DefaultRequestHeaders.Accept.Add(
 new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

 client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
 Convert.ToBase64String(
 System.Text.ASCIIEncoding.ASCII.GetBytes(
 string.Format("{0}:{1}", username, password))));

 using (HttpResponseMessage response = client.GetAsync(
 "https://{youraccount}.visualstudio.com/DefaultCollection/_apis/build/builds?definitions=" + id + "&statusFilter=completed&$top=5&api-version=2.0").Result)
 {
 response.EnsureSuccessStatusCode();
 string responseBody = response.Content.ReadAsStringAsync().Result.ToString();
 JObject json = JObject.Parse(responseBody);
 values = JsonConvert.DeserializeObject(json.ToString());
 myList.Add(values); 
 }
 }
 }
 catch (Exception ex)
 {
 Console.WriteLine(ex.ToString());
 }

 }

Buildvalues is a model which i had created from the json file which i received from the above code. Here i had used only the required fields in the model class

public class BuildValues
 {
 public List value { get; set; }
 }
 public class Build
 {
 public string status { get; set; }
 public string result { get; set; }
 public string buildNumber { get; set; }
 public string startTime { get; set; }
 public string finishTime { get; set; }
 public RequestedFor requestedFor { get; set; } 
 public Definition definition { get; set; }
 public RequestedBy requestedBy { get; set; }
 }
 public class RequestedFor
 {
 public string displayName { get; set; } 
 }
 public class RequestedBy
 {
 public string displayName { get; set; }
 }
 public class Definition
 {
 public string name { get; set; }
 }

You can see i am passing an id in the GetBuilds method. We are getting the id using the same code as in GetBuilds method except for we change the following snippet :

BuildDef obj = new BuildDef(); 
using (HttpResponseMessage response = client.GetAsync(
 "https://{youraccount}.visualstudio.com/DefaultCollection/_apis/build/definitions?api-version=2.0").Result)
 {
 response.EnsureSuccessStatusCode();
 string responseBody = response.Content.ReadAsStringAsync().Result.ToString();
 //var test = JsonConvert.DeserializeObject(responseBody);
 JObject json = JObject.Parse(responseBody);
 obj = JsonConvert.DeserializeObject(json.ToString());
 PassObj(obj);
 }

Here we use a similar model class which takes only id

 public class BuildDef
 {
 public List value { get; set; }
 }
 public class Value
 {
 public int id { get; set; }
 }

Since we have more build definitions we get almost 10 build IDs and in foreach loop we can call the GetBuilds

 foreach (var x in obj.value)
 {
 GetBuilds(x.id, myList);
 }

Then get the values to a List. and populate it accordingly into a nested repeater. Below screenshot shows how I got the values and displayed in my Sitecore project.

build

Hope this post was useful. Please contact me if any doubts/clarifications. Also you can share your ideas on the same if you have used any.

SITECORE BLOBS TABLE GROWING OUT OF CONTROL

This is my introduction post. And I am wishing to share an issue which made us worried  for about 1 month.

Over a past few days, I was facing abnormality in our Production WEB database. The size got increased from 37 GB to 110 Gb within 15 days.
But the issue was happening only in the WEB database not master. Then we ran the following query in SQL server Web database to check the size of each tables.
sql_query_size
After executing the query we were able to see the size of all tables in the Web database and dbo.Blobs database size has got a rapid increase of 60GB in last 2 weeks. And as we all know this table will store all media library assets and also it can quickly inflate the size of your content database.
So we wanted to stop this out of control growth of Blobs table and we tried 3 solutions which I have described below :
1) We tried to run a Cleanup Database task from Sitecore on the WEB database . But after running a number of times, each time we were getting an SQL timeout error.

Then we found a useful blog of Kiran Patil
Clean Up Database

We found that It was causing an error due to Default timeout for running SQL query was not enough for job to get its job done. So we tried increasing the “DefaultSQLTimeout” value to 12 hrs because the database size was very large.

But the cleanup job was not completed again it ran for more time and would suddenly stop in the middle and we had to start from beginning. So we stopped this approach for sometime and implemented a alternate solution.

2) Took a bacpac(database backup) of a clean Sitecore 8.0 web database. We did not want to disturb the Production database. So restored the new database to the QA SQL
server. Then changed the connection string information of the QA CM server to point to the master database in production and the web database that was restored from the
bacpac. Then using the QA Sitecore server to log in and do a full publish with all languages included.

As it was a full republish, it took more time and sometimes in the middle it stopped. So from the second time instead of going for Republish, we did Smart publish and finally the
publish was done successfully.

Then we restored the new WEB database to the production server and changed the Connection string to point to the new database. And finally the database size was reduced.

3) But after executing the above solution, there was no increase of Blobs table for 2 weeks, But after that we found again the size was increasing.
Now as suggested by Sitecore and in one of the blogs, we tried to delete top 1000 unused blobs from the table and automated it with Azure automated scripts(since our website is
hosted in Azure) and kept the time interval for 4 hours. Now after every 4 hours top 1000 rows from the table in which there is unused blobs will get deleted.

Here is the script we used :sql_query_delete

And it worked 🙂

But after the release of Sitecore 8.2 onwards, we have an admin page “/sitecore/admin/DbCleanup.aspx” which has an option for Selecting the option for only cleaning Blobs table as shown in the image.
cleanup_database

I hope this post was useful. Please do share other approaches that you may have adopted in your Sitecore implementations.