Select to view content in your preferred language

Synchronize edit to secure services

3243
7
Jump to solution
06-27-2012 08:18 AM
RobertMEIER
Regular Contributor
I have code that works with unsecure services, but when I add the secure stuff and try to sync to a secure service I am getting a NullReferenceException error.

I think the only part I have to add for security is setting the TokenCredential property on the MobileServiceConnection object, is that right??

Code:
MobileServiceConnection connection = new MobileServiceConnection();
            connection.TokenCredential = new ESRI.ArcGIS.Mobile.CatalogServices.TokenCredential("UserName", "Password");
            connection.Url = frmMap.staticMapForm._dataURL;

            tbxSyncMsg.Text = tbxSyncMsg.Text + "Synchronize Starting...\r\n\r\n";

            int totalBytesSent = 0;
            foreach (Layer l in frmMap.staticMobileCache.Layers)
            {
                FeatureLayer fl = l as FeatureLayer;
                //if ((fl != null))
                //{

                FeatureLayerSyncAgent agent = new FeatureLayerSyncAgent(fl);

                agent.MapDocumentConnection = connection;
                agent.SynchronizationDirection = SyncDirection.UploadOnly;
                SyncResults sr = agent.Synchronize();
                string msg = string.Empty;
                if (sr.Exception == null)
                {
                    msg = tbxSyncMsg.Text + String.Format("{0} Synchronizing\r\n{1} bytes sent\r\n\r\n", fl.Name, sr.DataSizeSent);

                    //tbxSyncMsg.Text = String.IsNullOrEmpty(tbxSyncMsg.Text) ? msg : tbxSyncMsg.Text + "/r/n" + msg;
                    tbxSyncMsg.Text = msg;
                    tbxSyncMsg.SelectionStart = tbxSyncMsg.Text.Length;
                    tbxSyncMsg.ScrollToCaret();
                    Application.DoEvents();
                    totalBytesSent += sr.DataSizeSent;
                    //crPosted = true;
                }
                else
                {
                    msg = tbxSyncMsg.Text + String.Format("{0} Failed to Synchronize\r\nError: {1}\r\n\r\n", fl.Name, sr.Exception.Message);
                    tbxSyncMsg.Text = msg;
                    tbxSyncMsg.SelectionStart = tbxSyncMsg.Text.Length;
                    tbxSyncMsg.ScrollToCaret();
                    //tbxSyncMsg.Text = String.IsNullOrEmpty(tbxSyncMsg.Text) ? msg : tbxSyncMsg.Text + "/r/n" + msg;
                    Application.DoEvents();
                }
                //}
            }

Also, when this runs I can see in the Immediate window the following:

A first chance exception of type 'System.UriFormatException' occurred in System.dll
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
A first chance exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
A first chance exception of type 'System.Net.WebException' occurred in System.dll
A first chance exception of type 'System.NullReferenceException' occurred in ESRI.ArcGIS.Mobile.dll

Any help is appreciated!

-bert
0 Kudos
1 Solution

Accepted Solutions
CiprianLazar
Deactivated User
The simplest way to accept any untrusted certificate is to create a class like this
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy         {             public TrustAllCertificatePolicy()             {             }              public bool CheckValidationResult(ServicePoint sp,                 System.Security.Cryptography.X509Certificates.X509Certificate cert,                  WebRequest req,                  int problem)             {                 return true;             }         }

and before accessing the MobileServiceConnection you should issue this
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();

Obviously, this is not the safest way to go, because this will accept ANY certificate  and this could be a problem.

You could pass the responsability to the user and ask him if he wishes to continue using this class:
public class QueryTrustCertificatePolicy : System.Net.ICertificatePolicy         {             private const uint CERT_E_UNTRUSTEDROOT = 0x800B0109;              public QueryTrustCertificatePolicy()             {             }              public bool CheckValidationResult(ServicePoint sp,                 System.Security.Cryptography.X509Certificates.X509Certificate cert, WebRequest req, int problem)             {                 bool returnValue = problem == 0;                  if ((uint)problem == CERT_E_UNTRUSTEDROOT)                 {                     if (System.Windows.Forms.MessageBox.Show("The security cetificate is not from a trusted certification authority (" + cert.GetIssuerName() + "). Do you want to proceed?",                         "Security Alert",                         System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question,                         System.Windows.Forms.MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)                         returnValue = true;                 }                 return returnValue;             }         }

and issue this command before accessing the MobileServiceConnection
System.Net.ServicePointManager.CertificatePolicy = new QueryTrustCertificatePolicy();


Hope this helps

View solution in original post

0 Kudos
7 Replies
CiprianLazar
Deactivated User
You are right. The only part that you have to add is that TokenCredential property.
I was having a similar problem because of a bad config file on the server. The MobileServiceConnection gets the token from an url that the catalog service is supplying. In my case, that url contained a bad port. I was able to find the error using a another way of setting the credentials.  You can try using and debugging (to see the variables values) this code:

ESRI.ArcGIS.Mobile.CatalogServices.TokenCredential tc =
                                new ESRI.ArcGIS.Mobile.CatalogServices.TokenCredential("user", "password");
ESRI.ArcGIS.Mobile.CatalogServices.CatalogService cs =
    new ESRI.ArcGIS.Mobile.CatalogServices.CatalogService();
cs.Url = ESRI.ArcGIS.Mobile.CatalogServices.CatalogService.GetCatalogServiceUrlFromServiceUrl(_mobileServiceConnection1.Url);
bool requiresToken = cs.RequiresTokens();
if (requiresToken)
{
    string tokenService = cs.GetTokenServiceURL();
    tokenService += ""; //** just to see it in the debugger. This was wrong in my case
    _mobileServiceConnection1.Url =
        ESRI.ArcGIS.Mobile.CatalogServices.TokenGenerator.GenerateAndApplyToken(_mobileServiceConnection1.Url, tc);
}


Alternatively, if you know the token service url, you could try accessing the secure service this way:

ESRI.ArcGIS.Mobile.CatalogServices.TokenCredential tc =
                                new ESRI.ArcGIS.Mobile.CatalogServices.TokenCredential("user", "password");
string token = ESRI.ArcGIS.Mobile.CatalogServices.TokenGenerator.GenerateToken("https://xxx.xxx.xxx.xxx/ArcGIS/tokens/", tc);
_mobileServiceConnection1.Url += "?token=" + token;



Another cause for failing to access the secure service could be the security certificate from the server (if you are using https). It that's an untrusted certificate, you should make sure that you accept it on the mobile device (you can also do it programatically; I could give you that code also if you need it)
0 Kudos
RobertMEIER
Regular Contributor
Thanks for the response!

I have tried to code you gave and am getting this error:

Could not establish secure channel for SSL/TLS

a google search tell me that this is caused by an untrusted certificate, so if you could pass along that code, I'd really appreciate it!

Thanks!

-bert
0 Kudos
CiprianLazar
Deactivated User
The simplest way to accept any untrusted certificate is to create a class like this
public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy         {             public TrustAllCertificatePolicy()             {             }              public bool CheckValidationResult(ServicePoint sp,                 System.Security.Cryptography.X509Certificates.X509Certificate cert,                  WebRequest req,                  int problem)             {                 return true;             }         }

and before accessing the MobileServiceConnection you should issue this
System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();

Obviously, this is not the safest way to go, because this will accept ANY certificate  and this could be a problem.

You could pass the responsability to the user and ask him if he wishes to continue using this class:
public class QueryTrustCertificatePolicy : System.Net.ICertificatePolicy         {             private const uint CERT_E_UNTRUSTEDROOT = 0x800B0109;              public QueryTrustCertificatePolicy()             {             }              public bool CheckValidationResult(ServicePoint sp,                 System.Security.Cryptography.X509Certificates.X509Certificate cert, WebRequest req, int problem)             {                 bool returnValue = problem == 0;                  if ((uint)problem == CERT_E_UNTRUSTEDROOT)                 {                     if (System.Windows.Forms.MessageBox.Show("The security cetificate is not from a trusted certification authority (" + cert.GetIssuerName() + "). Do you want to proceed?",                         "Security Alert",                         System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question,                         System.Windows.Forms.MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)                         returnValue = true;                 }                 return returnValue;             }         }

and issue this command before accessing the MobileServiceConnection
System.Net.ServicePointManager.CertificatePolicy = new QueryTrustCertificatePolicy();


Hope this helps
0 Kudos
LeeGraham
Occasional Contributor
I'd like to see the code for accepting a server certificate, if you can share....
0 Kudos
LeeGraham
Occasional Contributor
Never mind - I see the code. Thanks.
0 Kudos
CarmaGerber2
Emerging Contributor
Hello

I am new to using Mobile applications. I'm trying to sync between ArcGIS for Windows Mobile 10.0 and ArcGIS Server 10.0 and I assume its failing because of the security on my web services (IIS).
How do I use the code you have to accept any untrusted certificate? Is this the answer to the iussue I am also having?

Thanks so much!

Carma
0 Kudos
CiprianLazar
Deactivated User
Hello

I am new to using Mobile applications. I'm trying to sync between ArcGIS for Windows Mobile 10.0 and ArcGIS Server 10.0 and I assume its failing because of the security on my web services (IIS).
How do I use the code you have to accept any untrusted certificate? Is this the answer to the iussue I am also having?

Thanks so much!

Carma


The code I wrote above is for use in a custom ArcGIS Mobile application (built by yourself using ArcGIS Mobile SDK). If that's the case, you can create one of those two classes in a separate file, and just before accessing the first time your MobileServiceConnection object in your code, set the System.Net.ServicePointManager.CertificatePolicy to a new instance of your chosen class. That's all.

Good luck!
0 Kudos