Friday, 6 February 2015

SQL for showing outstanding replication commands

The collection of T-SQL below helps identify outstanding replication commands
use distribution
go
select * from dbo.MSarticles
where article_id IN (SELECT Article_id from MSrepl_commands
where xact_seqno = 0x0002E17600000131000600000000)

sp_browsereplcmds @xact_seqno_end = '0x0002E17600000131000600000000'
sp_browsereplcmds @xact_seqno_start = '0x0002E17600000131000600000000', @xact_seqno_end = '0x0002E17600000131000600000000', @Command_id = 1, @publisher_database_id = 1

select * FROM MSArticles a where article in ('DiscountCode', 'DiscountCodeCountry', 'DiscountRule')
select * from M

-- Discount Code
sp_browsereplcmds @article_id = 60, @xact_seqno_end = '0x0002E17600000131000600000000'
sp_browsereplcmds @article_id = 61, @xact_seqno_end = '0x0002E17600000131000600000000'
sp_browsereplcmds @article_id = 62, @xact_seqno_end = '0x0002E17600000131000600000000'

EXECUTE sp_replmonitorsubscriptionpendingcmds 
@publisher ='.\PublisherDb', -- Put publisher server name here
@publisher_db = 'MyPubDb', -- Put publisher database name here
@publication ='Discount-Publication',  -- Put publication name here
@subscriber ='.\SubscriberDb', -- Put subscriber server name here
@subscriber_db ='MySubDb', -- Put subscriber database name here
@subscription_type ='0' -- 0 = push and 1 = pull
The SQL below shows the replication performance for a table.

use distribution
go

select min(dh.delivery_latency) min, avg(dh.delivery_latency) avg, MAX(dh.delivery_latency) max
from MSarticles a 
inner join MSpublications (nolock) p on a.publication_id = p.publication_id
inner join MSsubscriptions (nolock) s ON p.publication_id = s.publication_id and s.article_id = a.article_id
inner join master..sysservers (nolock) ss ON s.subscriber_id = ss.srvid 
inner join master..sysservers (nolock) srv ON srv.srvid = p.publisher_id 
inner join MSdistribution_agents (nolock) da ON da.publisher_id = p.publisher_id  AND da.subscriber_id = s.subscriber_id and da.publication = p.publication
inner join distribution.dbo.MSdistribution_history (nolock) dh on dh.agent_id = da.id
where a.destination_object = 'MyTable'
and s.subscriber_db = 'MyDB'

Find out the replication properties of a table

The script below lists the publisher, subscriber and publication for a replicated table in SQL Server. It is executed against the distribution database.

use distribution
go

-- View the replication properties of a table
select a.publisher_db, s.subscriber_db, a.article, p.publication, p.publication_type
from MSarticles a 
inner join MSpublications p on a.publication_id = p.publication_id
inner join MSsubscriptions s ON p.publication_id = s.publication_id and s.article_id = a.article_id
inner join master..sysservers ss ON s.subscriber_id = ss.srvid 
inner join master..sysservers srv ON srv.srvid = p.publisher_id 
inner join MSdistribution_agents da ON da.publisher_id = p.publisher_id  AND da.subscriber_id = s.subscriber_id and da.publication = p.publication
where a.destination_object like '%discountusage%'

Testing a REST API with Powershell

With the following Powershell script, you can issue a POST request to a REST endpoint

add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srvPoint, X509Certificate certificate,
            WebRequest request, int certificateProblem) {
            return true;
        }
    }
"@

[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

$uri = 'https://myurl.com/v1/MyResource?param=true'

$body = 
'{
    "products": [
        {
            "productId": 1,
            "quantity": 0
        },
        {
            "productId": 2,
            "quantity": 0
        }
    ]
}'


$response = Invoke-WebRequest -Uri $uri -Method POST -Body $body -ContentType 'application/json; charset=utf-8' 
$response.Headers

Tuesday, 30 December 2014

"Clone in Desktop" doesn't launch GitHub for Windows

"Clone in Desktop" wasn't launching GitHub for Windows.
Fortunately Joe Freeman solved it.

You either
a. Log in to GitHub in the Web Browser before clicking the "Clone in Desktop" link
b. Drag the URL of the repository to GitHub for Windows

Sunday, 28 December 2014

Galaxy Tab S doesn't connect to ADB (Android Device Bridge)

After receiving a new Galaxy Tab S, I noticed it would not connect to Eclipse or ADB for debugging.

(I had enabled Developer options by clicking on Settings > General > About Device > Android Version 7 times).

The solution is that you have to download the USB driver from Samsung's site. This then enables the following drivers:

Tuesday, 23 December 2014

Sitecore 6.6, Web API 1.2 and the message "An attempted to execute remote call was declided, because current mode is 'off'"

We are running Sitecore with MVC and installed the Web API 1.2.

When accessing the URL
http://<hostname>/-/item/v1/?query=/sitecore/content/*

from within Chrome and Postman it was running an error page.
After some extensive reading, experimenting, writing a custom pipeline processor and using Reflector, I finally solved it.

Firstly I turned on logging to ALL in App_Config\Sitecore.log4net.config.

    
    
  

This showed the following error message in the event log:

"An attempted to execute remote call was declided, because current mode is 'off'"

er... this should mean "declined", but never mind. Carrying on:

Reflector indicated that the CheckMode processor found the itemwebapi.mode setting was turned to "Off".

But hold on, my settings were on:
Include\Sitecore.ItemWebApi.config:

<site name="website">
        <patch:attribute name="itemwebapi.mode">StandardSecurity</patch:attribute>
        <patch:attribute name="itemwebapi.access">ReadOnly</patch:attribute>
        <patch:attribute name="itemwebapi.allowanonymousaccess">true</patch:attribute>
      </site>

So then I wrote a processor to fit within the pipeline to evaluate the problem.
The following class was written and added to a class library:

using System;
using System.Diagnostics;
using Sitecore.Diagnostics;
using Sitecore.Pipelines.HttpRequest;

namespace TestPipeline
{
    public class TestProcessor : HttpRequestProcessor
    {
        public override void Process(HttpRequestArgs args)
        {
            var context = args.Context.Items["Sitecore.ItemWebApi.Context"];
            Console.WriteLine("Hello World");
        }
    }
}

the class library requires references to Sitecore.Kernel and System.Web.

Using reflector, it can be seen that the Web API settings are loaded in SetRuntimeSettings, which runs after SiteResolver:

<processor type="Sitecore.ItemWebApi.Pipelines.HttpRequest.SetRuntimeSettings, Sitecore.ItemWebApi" patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.SiteResolver, Sitecore.Kernel']" />

Therefore the pipeline was inserted after SiteResolver:

<processor type="Sitecore.Pipelines.HttpRequest.SiteResolver, Sitecore.Kernel" />
<processor type="TestPipeline.TestProcessor, TestPipeline" />
<processor type="Sitecore.Pipelines.HttpRequest.UserResolver, Sitecore.Kernel" />

A debugger was then attached to the wp3 process and a breakpoint put within the processor.
Looking at args.Context.Items["Sitecore.ItemWebApi.Context"].Settings.Mode it was indeed turned to off and not StandardSecurity.

It was then determined that in the Web API config the site had the default sitename:

<site name="website">

whereas in Include\Sitecore.SiteDefinition.config the sitename was patched to something else:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <sites>
      <site br="" name="checkout" patch:instead="site[@name='website']">
</site></sites></sitecore></configuration>b

Removing Include\Sitecore.SiteDefinition.config fixed the problem.
To keep the file, the following attributes were added:
itemwebapi.mode="StandardSecurity"
itemwebapi.access="ReadOnly"
itemwebapi.allowanonymousaccess="true"

Solved: The WebAPI config was assuming the default site name "website" whereas this had been configured to something else.