After resolving the previous issue with the Sitecore reporting database rebuild getting stuck on the starting process state. I was able to progress to the next step where it managed to get stuck on the StoppingDataRecording process state.
The logs were clean from errors in relation to this issue, yet it would stay stuck on this state until cancelled.
It turns out that the content management server which I was running the rebuild off of had it's configuration files configured incorrectly. As there was no dedicated processing server in this environment the content management server should have been setup as content management + processing.
It was the disabled processing related configurations which was causing the reporting database rebuild to get stuck.
Software development blog focusing on the Sitecore Experience Platform and Sitecore Experience Commerce.
Wednesday, June 28, 2017
Sitecore reporting database rebuild SQL script
As a part of the instructions of rebuilding the reporting database in Sitecore, there is a step where some SQL needs to be run manually on the database. When the process state is WaitReadyToReceiveData the contents of 7 database tables need to move from the primary DB to the secondary DB. The instructions state:
In the Rebuild Reporting Database page, when you see Waiting to receive to data status, copy the following marketing definition tables from the primary to the secondary reporting database:The SQL to copy this data is as follows:
- CampaignActivityDefinitions
- GoalDefinitions
- OutcomeDefinitions
- MarketingAssetDefinitions
- Taxonomy_TaxonEntity
- Taxonomy_TaxonEntityFieldDefinition
- Taxonomy_TaxonEntityFieldValue
INSERT INTO [reporting.secondary]..CampaignActivityDefinitions SELECT * FROM [reporting]..CampaignActivityDefinitions INSERT INTO [reporting.secondary]..GoalDefinitions SELECT * FROM [reporting]..GoalDefinitions INSERT INTO [reporting.secondary]..OutcomeDefinitions SELECT * FROM [reporting]..OutcomeDefinitions INSERT INTO [reporting.secondary]..MarketingAssetDefinitions SELECT * FROM [reporting]..MarketingAssetDefinitions INSERT INTO [reporting.secondary]..Taxonomy_TaxonEntity SELECT * FROM [reporting]..Taxonomy_TaxonEntity INSERT INTO [reporting.secondary]..Taxonomy_TaxonEntityFieldDefinition SELECT * FROM [reporting]..Taxonomy_TaxonEntityFieldDefinition INSERT INTO [reporting.secondary]..Taxonomy_TaxonEntityFieldValue SELECT * FROM [reporting]..Taxonomy_TaxonEntityFieldValueEnsure that the database names are updated to reflect that of your environment.
Tuesday, June 27, 2017
Sitecore Rebuild Reporting Database gets stuck on Starting
After moving over to a new MongoDB host, and with fresh data I needed to rebuild the reporting database in Sitecore to get everything in sync. The problem was that it got stuck in the Starting state and never progressed.
Looking into the logs the following error was visible:
![]() |
Process State does not change from starting |
ERROR Message: Exception of type 'System.Web.HttpUnhandledException' was thrown. - InnerException: System.Data.SqlClient.SqlException (0x80131904): Cannot open database "Sitecore_Reporting_Secondary" requested by the login. The login failed.It turned out to be a permission issue with the reporting secondary database, fixing that up allowed the rebuild to continue.
Login failed for user 'MyAccount'.
Thursday, June 22, 2017
Sitecore Commerce Server profile definitions not found
Working inside the Commerce Server Manager, under the profile definitions I noticed a 404 not found page when selecting a definition (such as User Object).
This was due to a local website binding being missing.
![]() |
Sitecore Commerce Server - profile definition not found |
This was due to a local website binding being missing.
- Open up IIS Manager
- Select the default web site (or create this with an empty binding).
- Create a virtual directory called Widgets and set the physical path to c:\Program Files (x86)\Common Files\Microsoft Shared\Enterprise Servers\Commerce Server\Widgets
The profile definition will now load correct without error.
Friday, June 16, 2017
MVC controller action from JavaScript is returning 404
In developing front-end logic to call MVC controller actions (with Sitecore context), I noticed that the calls were returning a 404 from the delivery servers and not management servers.
The URL of the AJAX request was:
Investigation lead to the result that URLs on the delivery server were all being redirected to lowercase URLs. Hence the initiator for the AJAX call changing between servers. MVC controllers will work with both uppercase and lowercase URLs, so the problem was not likely on that end. What appeared to be happening was that the redirect was messing up the call and requesting it as a standard page (hence the 404 response, which was actually returning the IIS 404 page).
Changing the request URL in AJAX to be lowercase fixed the issue.
The URL of the AJAX request was:
url: "/Accounts/Register"Inside the console, that request appeared as follows
![]() |
The request on delivery server returned a 404 |
![]() |
The request on the management server worked |
Changing the request URL in AJAX to be lowercase fixed the issue.
url: "/Accounts/Register"
Tuesday, June 13, 2017
Anti forgery tokens on MVC controllers called via JavaScript
In a previous post I demonstrated how an MVC controller (which inherits from SitecoreController) can be used to identify a contact via JavaScript. The next step is to prevent Cross-Site Forgery Requests (CSRF) via the use of an anti forgery token. Because this is a service call and not form post, it's a slightly different method to hook this all together.
Users of AngularJS and Web API can refer to this example: CSRF in AngularJS/Web API on Web Forms.
Users of AngularJS and Web API can refer to this example: CSRF in AngularJS/Web API on Web Forms.
The anti forgery token
The first step is to place the hidden field on the page which contains the anti-forgery token. This would be placed on the layout, or a view if you are restricting it to certain site features. Web forms users would place this on a master page.
@using System.Web.Helpers @Html.AntiForgeryToken()or
<%@ Import Namespace="System.Web.Helpers" %> <%# AntiForgery.GetHtml() %>
Token validation
The following attribute will be used on the MVC controller and validates that the token is present and matches the users cookie correctly.
using System.Web.Mvc; namespace MyProject { public class ValidateAntiForgeryHeader : System.Web.Mvc.FilterAttribute, System.Web.Mvc.IAuthorizationFilter { public void OnAuthorization(AuthorizationContext filterContext) { string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME); if (clientToken == null) { throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME)); } string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value; if (serverToken == null) { throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME)); } System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken); } private const string KEY_NAME = "__RequestVerificationToken"; } }
The MVC controller
Now we just need to place the attribute on any actions which require anti forgery. Generally this happens on calls where data is being sent through, such as: login, registration etc.
[HttpPost] [ValidateAntiForgeryHeader] public ActionResult ForgottenPassword(string emailAddress) { }
The service call
Now the service call just needs to pass through the token in the header.
var token = $('input[name="__RequestVerificationToken"]').val(); $.ajax({ type: "POST", url: "/Contact/IdentifyContact", headers: { '__RequestVerificationToken': token }, data: JSON.stringify({'emailAddress': 'testing@email.com'}), contentType: "application/json; charset=utf-8", dataType: "json", success: function (result) { }, error: function (request, status, error) { } });
Conclusion
Now the service calls are protected against CSRF, and of course in a Sitecore implementation this type of service call will still have access to the Sitecore context.
Monday, June 12, 2017
ServiceStack the clean way to integrate API calls
ServiceStack is a powerful and fast framework which adds value to any .NET solution. It handles a fair bit of functionality and features, as the image below shows). This post will be going over just how simple it is to integrate a REST API call into your solution using ServiceStack.
In this example, I am going to be calling an API to get weather data using Open Weather Map. This API has limited free access, but does require signup to get an API key. An example of the call is shown below, it simply takes in the city along with an app ID.
What comes out of the box with ServiceStack |
The request model
You'll notice with the request model below that the call type is defined as get, the return object is referenced directly, and that DataMember is the service's variable name (which allows for cleaner classes). The route does not include any querystring as this is automatically handled, this could be something like /weather/{q/ if a parameter is part of the route.
using ServiceStack; using System.Runtime.Serialization; namespace MyProject { [Route("/weather", "GET")] [DataContract] public class CurrentWeatherRequestModel : IReturn<CurrentWeatherResponseModel> { [DataMember(Name = "q")] public string City { get; set; } [DataMember(Name = "appid")] public string ApiKey { get; set; } } }
The response model
The response model is simple enough, DataMember could also be used to have a cleaner class, but this example demonstrates that ServiceStack will map directly to the model.
using System.Collections.Generic; namespace MyProject { public class CurrentWeatherResponseModel { public Coord coord { get; set; } public Sys sys { get; set; } public List<Weather> weather { get; set; } public Main main { get; set; } public Wind wind { get; set; } public Rain rain { get; set; } public Clouds clouds { get; set; } public int dt { get; set; } public int id { get; set; } public string name { get; set; } public int cod { get; set; } } public class Coord { public int lon { get; set; } public int lat { get; set; } } public class Sys { public string country { get; set; } public int sunrise { get; set; } public int sunset { get; set; } } public class Weather { public int id { get; set; } public string main { get; set; } public string description { get; set; } public string icon { get; set; } } public class Main { public double temp { get; set; } public int humidity { get; set; } public int pressure { get; set; } public double temp_min { get; set; } public double temp_max { get; set; } } public class Wind { public double speed { get; set; } public double deg { get; set; } } public class Rain { public int __invalid_name__3h { get; set; } } public class Clouds { public int all { get; set; } } }
The call
Finally here is the actual service call, in 3 simple lines the API is called and the result is mapped back to your response class. The base URL for the API is also set here.
using ServiceStack; namespace MyProject { public static class GetCurrentWeather { public static CurrentWeatherResponseModel ByCity(CurrentWeatherRequestModel request) { var client = new JsonServiceClient("http://api.openweathermap.org/data/2.5"); client.Headers.Add("ContentType", "application/json"); return client.Get(request); } } }
Conclusion
As you can see from the example above, ServiceStack is a really clean/simple way of making service calls in your c# solutions. The code is easily readable, can be integrated into unit tests and works well across multiple environments, if the base URL is a configurable variable.
Subscribe to:
Posts (Atom)