Quantcast
Channel: Http Client Protocol Issues (and other fun stuff I support)
Viewing all 140 articles
Browse latest View live

Problem Signing with SafeNet EV Certificate

$
0
0

I had an interesting case that I want to share in the event anyone else experiences this problem.  In this case a Symantec certificate stored on a SafeNet USB dongle was being used to sign a Windows Store app in Visual Studio.  The signing was failing.  Visual Studio reported: “SignTool Error:  An unexpected internal error has occurred”.  These guidelines were followed and everything seemed in order:

http://msdn.microsoft.com/en-us/library/windows/apps/br230260(v=vs.110).aspx

During packaging, Visual Studio validates the specified certificate in the following ways:

· Verifies the presence of the Basic Constraints extension and its value, which must be either Subject Type=End Entity or unspecified.

· Verifies the value of the Enhanced Key Usage property, which must contain Code Signing and may also contain Lifetime Signing. Any other EKUs are prohibited.

· Verifies the value of the KeyUsage (KU) property, which must be either Unset or DigitalSignature.

· Verifies the existence of a private key exists.

· Verifies whether the certificate is active, hasn’t expired, and hasn't been revoked.

Solution

I used Process Monitor (Procmon) to determine the command line that was being used and then using the command line SignTool.exe to issue the same command, saw that it was returning this:  Error: SignerSign() failed." (-1073741275/0xc0000225)

SafeNet had the solution for this problem.  Using the SafeNet Client Authentication tools it was found that there were ‘Orphan Objects’ on the device.  Removing these resulted in being able to use this device to sign the application successfully!

SafeNet

Let me know if this helps you out!


How to: Convert an Image to Grayscale

$
0
0

I ran across an issue where I wanted to convert an Image in a Windows Store app  to grayscale and could not find a great example.  So… here is one for you to try!

private async Task imageToGrayscale(Image src, Image dest)
        {
            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
            //Get existing src pixels in a Byte[] (always is BRGA formate
            await renderTargetBitmap.RenderAsync(src);
            IBuffer pixelSrc = await renderTargetBitmap.GetPixelsAsync();
            Byte[] destBytes = new Byte[pixelSrc.Length];

            for (int i = 0; i < pixelSrc.Length; i += 4)
            {
                double b = (double)pixelSrc.GetByte((uint)i) / 255.0;
                double g = (double)pixelSrc.GetByte((uint)i+1) / 255.0;
                double r = (double)pixelSrc.GetByte((uint)i+2) / 255.0;

                byte a = pixelSrc.GetByte((uint)i + 3);

                double e = (0.21 * r + 0.71 * g + 0.07 * b) * 255;
                byte f = Convert.ToByte(e);

                destBytes[i] = f;
                destBytes[i + 1] = f;
                destBytes[i + 2] = f;
                destBytes[i + 3] = a;

            }

            WriteableBitmap destWB = new WriteableBitmap(renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight);
            using (Stream pixelStream = destWB.PixelBuffer.AsStream()) {
                pixelStream.Seek(0, SeekOrigin.Begin);
                pixelStream.Write(destBytes, 0, destBytes.Length);
                destWB.Invalidate();

            }
            destImage.Source = destWB;

        }

If you like it, drop me a note of thanks!

Quicky Post: Troubleshooting Receiving Push Notifications using Android Eclipse

$
0
0

Preview/Draft

Sometimes I like to fire off information without making it pretty in hopes it will help someone struggling with an issue.  So… I apologize up-front for the brevity of this post and promise to incorporate it into a larger troubleshooting blog when I get a chance to breathe Smile

Issue

I confirmed Windows Azure Mobile Services was able to communicate with GCM (Google Cloud Messaging) and had no errors sending the notification to GCM.  But how could I see how this got or didn’t get to my Android Emulator?

Server side

I was able to confirm that there were no errors by dumping out the result of doing a push.gcm.send using this script (from our tutorial):

push.gcm.send(item.handle, item.text, {
    success: function (response) {
        console.log('Push notification sent: ', response);
    }, error: function (error) {
        console.log('Error sending push notification: ', error);
    }
});

And opening the LOGS tab saw this result:

Push notification sent: {
multicast_id: 4877295250689814000,
success: 1,
failure: 0,
canonical_ids: 0,
results: [
{ message_id: '0:1392395679428889%0d284a0ef9fd7ecd' } ], invalidIds: [], updatedIds: {} }

So how to see what if anything is happening on the client?  The message_id looks promising!

Client side

Running the program from Eclipse and ensuring Log Cat is running I was able to confirm that I am getting the message from the GCM service!

02-14 11:34:39.769: I/GCM(624): GCM message com.example.jsanderspushgcm 0:1392395679428889%0d284a0ef9fd7ecd

I clicked on the message to set up a verbose filter for GCM:

image

And now I can easily filter and see what GCM logs are showing me!

Conclusion

I could also use fiddler as a proxy to see network traffic but with a little logging and knowledge of the available server and client side tools, was able to correlate the GCM messages quickly!

Let me know if this was useful to you!

Setting up Eclipse for Windows Azure Mobile Services Development

$
0
0

There were no detailed instructions for this and I ran into some problems when following our tutorial for this so here are my super easy to follow instructions.  I did this on Windows 8.1 64bit OS installed in a Hyper-V VM.  These instructions are for the 64 bit environment (I did not try the 32 bit).

Install the Android SDK

From the Android SDK download choose the big button on the right (link is this Download the SDK ADT Bundle for Windows):

image

Read the license agreement and if you don’t agree then STOP, otherwise grab the 64 bit SDK and download it:

image

Unzip the package (I put it in my documents in a folder I created called Android Development):

image

and read this:

http://developer.android.com/sdk/installing/bundle.html

For convenience pin a link to Eclipse.exe on your taskbar.  It is in the Eclipse sub-folder wherever you installed the android SDK and you can navigate there using Windows Explorer, right click on it and pin it:

image

Install the JDK

What is missing is now is the JDK.  Go here and install it:

http://www.oracle.com/technetwork/java/javase/downloads/index.html

Press the big Java button:

image

Accept the license agreement if you agree and download the Windows x64 version:

image

Once you have installed the JDK there is still more to go!

Workspace and additional components

Now we need some more components.

When you start Eclipse create a workspace in your Documents folder:

image

If everything is OK, and Eclipse starts go to the Android SDK Manager by choosing Window, Android SDK Manager.

image

When the Android SDK Manager comes up, Close Eclipse then return to the SDK Manager and add ‘Google Play Services’ by checking it (under Extras) and install that and any updates that were detected for you:

image

When that finishes, go back and select Google APIs and install that too:

image

You can close the Android SDK Manager now.

Configure the Emulator

In order to use Push notifications you need to configure an emulator that has the Google APIs.  To do this open Eclipse and go to Window, Android Virtual Device Manager:

image

Select the Nexus S by Google and hit the Create AVD… button:

image

For Target ensure you select Google APIs as shown below (important note: if you don’t see that option available, then you did not follow the steps I have listed above.  You must resolve this or you cannot test Push Notifications).

image

Now you can proceed with the Data and Push tutorials for Android!

Footnotes

If you get this error when running the Push Tutorial:

E/AndroidRuntime(1701): Caused by: java.lang.NoClassDefFoundError: com.google.android.gms.gcm.GoogleCloudMessaging

You need to ensure you reference the GooglePlay Library in your project

Right Click on your project and choose properties:

Then Android, Add the google-play-services_lib as shown:

image

Hit OK.

Conclusion

There are a couple of nuances for setting up Google Play Services and the SDKs to get started, but this should help you tremendously!  Drop me a note if you found this useful and be sure to follow me @jsandersrocks and my team @WSDevSol on twitter!

PowerShell Script to backup Windows Azure Mobile Services scripts

$
0
0

Listing for a PowerShell Script to backup Windows Azure Mobile Services scripts and configuration information.  I will get something more complete up on the Script Repository this next month!  This also assumes you have set your subscription active using Windows Azure PowerShell.  See How to install and configure Windows Azure PowerShell for more information.

function main()
{
    $startDir = Get-Location;
    $MobileServices =  ListMobileServices ;

    $MobileServices | foreach{
        # for every service create a directory 

        $MobileServiceName = $_.name;  
        $MobileServiceName;
        $MobileServiceDir = CreateMobileServiceDirectory($MobileServiceName);
        
        # and move to that directory
        Set-Location $MobileServiceDir;
         
        $ScriptList = ListScripts $MobileServiceName;
        $ScriptList;
        if ($ScriptList.table)
        {
            $tblScriptLoc = CreateMobileServiceDirectory("scripts");   
            Set-Location $tblScriptLoc;
            $ScriptList.table | foreach{
                $ScriptName = "table/{0}.{1}" -f $_.table, $_.operation;
                azure mobile script download $MobileServiceName $ScriptName;
                }
                #end foreach table
            Set-Location $MobileServiceDir;
        }
        if($ScriptList.scheduler)
        {
            $tblScriptLoc = CreateMobileServiceDirectory("scripts");   
            Set-Location $tblScriptLoc;
            $ScriptList.scheduler | foreach{
                $ScriptName = "scheduler/{0}" -f $_.name;
                azure mobile script download $MobileServiceName $ScriptName;
                }#end foreach scheduler
            Set-Location $MobileServiceDir;
        }
        if($ScriptList.api)
        {
            $tblScriptLoc = CreateMobileServiceDirectory("scripts");   
            Set-Location $tblScriptLoc;
            $ScriptList.api | foreach{
                $ScriptName = "api/{0}" -f $_.name;
                azure mobile script download $MobileServiceName $ScriptName;
                }
                #end foreach api
            Set-Location $MobileServiceDir;
        }
        if($ScriptList.shared)
        {
            $tblScriptLoc = CreateMobileServiceDirectory("scripts");   
            Set-Location $tblScriptLoc;
            $ScriptList.shared | foreach{
                $ScriptName = "shared/{0}" -f $_.name;
                azure mobile script download $MobileServiceName $ScriptName;
                }
                #end foreach shared
            Set-Location $MobileServiceDir;
        }

        #dump config to a json file:
        $tmp=""; azure mobile config list --json $MobileServiceName |  foreach{  $tmp += $_ };  New-Item "config.json" -ItemType file -Value $tmp;
        $tmp=""; azure mobile show --json $MobileServiceName |  foreach{  $tmp += $_ };  New-Item "details.json" -ItemType file -Value $tmp;
        $tmp=""; azure mobile job list --json $MobileServiceName |  foreach{  $tmp += $_ };  New-Item "job.json" -ItemType file -Value $tmp;
          

    Set-Location $startDir.Path;
    }; 
    #end foreach Service
}


function CreateMobileServiceDirectory()
{
    param( 
        [Parameter(Mandatory=$true)]
        $ServiceName
        )

    $loc = Get-Location;
    [string]$fullPath = "{0}\{1}" -f $loc.Path, $ServiceName;
    
    if(Test-Path $fullPath)
    {
        if ( Test-Path $fullPath -pathType Container)
        {
        }
        else
        {
            #error
        }
    }
    else
    {
        $newObj= New-Item $fullPath -ItemType directory;
    }

    return $fullPath;
}

function ListTables()
{
    param(
        [Parameter(Mandatory=$true)]
        $ServiceName
        )

    $TableTemp = "";
    
    $TMPP=azure mobile table list --json $ServiceName |  foreach{ 
        $TableTemp += $_;
        };  
    return ConvertFrom-Json($TableTemp);
}

function ListScripts()
{
    param(
        [Parameter(Mandatory=$true)]
        $ServiceName
    )
    $TableTemp = "";
    
    $TMPP=azure mobile script list --json $ServiceName |  foreach{ 
        $TableTemp += $_;
        };  
    return ConvertFrom-Json($TableTemp);
}

function ListMobileServices()
{
    $TempJsonString= ""; 
    # Get a list of Services as Json objects
    # since it is a bunch of Line feeds have to concatonate the string
    azure mobile list --json |  foreach{ $TempJsonString += $_  }; 
    return ConvertFrom-Json($TempJsonString);
}

#call Main!
main; 

How to use Fiddler with Windows Azure Mobile Services .NET (Preview) Backend

$
0
0

I was using the Windows Azure Mobile Services .NET (Preview) Backend and wanted to see the HTTPS traffic.  I found the best way is to use Fiddler and modify the application so it will send traffic through the Fiddler proxy.  By default Fiddler will not catch the localhost traffic so you need to do a little trick to get IIS Express (Cassini) to work with this setup (ref: http://docs.telerik.com/fiddler/observe-traffic/troubleshooting/notraffictolocalhost ).

Set up Fiddler like you normally would to capture all HTTPS traffic and modify your application code to point to localhost.fiddler instead of local host.  For example, in my C# client project I changed this:

sealed partial class App : Application
    {
        // This MobileServiceClient has been configured to communicate with your local
        // test project for debugging purposes. Comment out this declaration and use the one
        // provided below when you are done developing and deploy your service to the cloud.
        public static MobileServiceClient MobileService = new MobileServiceClient(
            "http://localhost:51039");

To this:

sealed partial class App : Application
    {
        // This MobileServiceClient has been configured to communicate with your local
        // test project for debugging purposes. Comment out this declaration and use the one
        // provided below when you are done developing and deploy your service to the cloud.
        public static MobileServiceClient MobileService = new MobileServiceClient(
            "http://localhost.fiddler:51039");

Now I get my traffic in the local scenario! 

I hope this helps!  Drop me a note if you found this useful!

Jeff

.NET Backend helpful links

$
0
0

Create a Staging .NET Backend for Testing

$
0
0

Debugging on your Live Service is bad!  For instance if you are breaking in the debugger while one of your users is trying to get data, that call will likely timeout.  Also it is difficult to isolate an issue if multiple unplanned requests are coming into your service.  If you have some things you need to test or debug with your .NET backend, you can easily publish your .NET Backend code to a ‘Staging’ service to do your debugging.

Setup

From your .NET Backend project choose publish, but click ‘Windows Azure Mobile Services’ (under ‘Select a publish target’) to publish to a new Mobile Service.

image

Hit ‘New…’ to create a new mobile service

image

Give it a name (I like Staging-<<NAME OF LIVE SERVICE HERE>>)

image

Publish it!

And now you can debug it!

Debug

image

Notes

This is just a quick publish blog to give you some ideas.  Keep the feedback coming and we can improve this post together!

By using a ‘Staging’ area you will not disrupt your service operations.

You can copy the Azure DB data to the new DB that was created, but that is beyond the scope of this quicky blog.


Creating a WebSite for Polling Live Tiles

$
0
0

You can very easily have your app Poll for Live Tiles.  What is cool about that is that you don't have to register for Push Notifications and you can easily show updates to all users of your apps with low overhead.  Also, the user never has to run your app for Live Tiles to update.

Review of the App side

To demo this, create a blank C# Windows Store app.  In the manifest set the Polling properties:

image

(you will see later how the {language} and {region} sections get filled in by the OS for you!)

It is THAT EASY!  The OS will poll that URI for the Tile Template information to use to update your Live tile.

 

Implement the Server

Here is a super simple Azure Web Site walkthrough to prove and show the concept

Using Visual Studio create a new blank ASP.NET Empty Web Site:

image

Add a Web Form to your site and call it something like TileUpdate.aspx:

image

Next remove all but the top line from the page layout:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="TileUpdate.aspx.cs" Inherits="_Default" %>

And in the .cs file, define your XML output and send it!

Copy Code:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;public partial class _Default : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e)
    {/// example:  AppManifest has this for the polling uri: http://jsanderspolltiles.azurewebsites.net/TileUpdate.aspx?language={language}&region={region}///           We get this on my en-US machine: /TileUpdate.aspx?language=en-US&region=US/// Poll mechanism can fill in the language and region for us:

        // Build the xmlString (or read it from something else... I really don't mind)
        StringBuilder xmlString = new StringBuilder();// Text for my tile update:string textToDisplay = "The world's top tourist destinations revealed";string strLanguage = Request.QueryString["language"];if (strLanguage != null)
        {//TODO: Switch on languageif (strLanguage != "en-US")
            {
                textToDisplay = strLanguage; // TODO: translate String to different language.  Just changing it to the language sent for now.}
        }string strRegion = Request.QueryString["region"];if (strRegion != null)
        {if (strRegion != "US")
            {
                textToDisplay = strRegion;
            }
        }// clear our the response.Response.Clear();// set content typeResponse.ContentType = "text/xml; charset=utf-8";// Build the xml template that conforms to the Tile template rules!xmlString.Append("<tile xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">");
        xmlString.Append("<visual lang=\"en-us\" version=\"2\">");
        xmlString.Append("<binding template=\"TileSquare150x150PeekImageAndText04\" fallback=\"TileSquarePeekImageAndText04\"><text id=\"1\">");
        xmlString.Append(textToDisplay);
        xmlString.Append("</text><image id=\"1\" src=\"http://appexblu.stb.s-msn.com/usappex/i/8E/2CB45E8861AD9E94E95A0D0A4C0.jpg\" /></binding>");
        xmlString.Append("<binding template=\"TileWide310x150ImageAndText01\" fallback=\"TileWideImageAndText01\"><text id=\"1\">");
        xmlString.Append(textToDisplay);
        xmlString.Append("</text><image id=\"1\" src=\"http://appexblu.stb.s-msn.com/usappex/i/D5/5333A8B47E2EDF659BFE7E6A267.jpg\" /></binding>");
        xmlString.Append("<binding template=\"TileSquare310x310ImageAndText01\"><text id=\"1\">");
        xmlString.Append(textToDisplay);
        xmlString.Append("</text><image id=\"1\" src=\"http://appexblu.stb.s-msn.com/usappex/i/EE/BDCE456C7A26968C1779C13589323.jpg\" /></binding>");
        xmlString.Append("<binding template=\"TileSquare70x70ImageAndTextOverlay01\"><text id=\"1\">");
        xmlString.Append(textToDisplay);
        xmlString.Append("</text><image id=\"1\" src=\"http://appexblu.stb.s-msn.com/usappex/i/8E/2CB45E8861AD9E94E95A0D0A4C0.jpg\" /></binding>");
        xmlString.Append("</visual></tile>");// Write and Response.Write(xmlString.ToString());// Flush the response to send itResponse.Flush();
    }
}

Note the comments in the code.  The app issuing the request can automatically fill in the region and the  language as arguments in the URI as you can see in the comments!  It is up to you to determine the logic of when and how to update the tile text and image in your web site.  It is left to you to change the text or image based on the language and region as well.

Then publish your Web Site!  (I used Azure Web Sites).  Using Azure Web Sites you can remote debug it easily too!

Test

Side load your app, then Pin the tile so the start screen.  It will immediately poll the URI you specified and update the tile!  To kick off the test again, you can wait 30 minutes or… Uninstall and install the app again.  You can use Fiddler to see the request and response.

Links

How to publish ASP.NET web site to Azure Web Sites

Tile Update

 

Drop me a note if you found this useful!  Follow me at @jsandersrocks and my team @WSDevSol

Always Drop and Create Local Database .NET Backend for Azure Mobile Services

$
0
0

In my early testing I wanted to always seed my Local Database.  By default the db was only dropped and reseeded if you changed the models.  There is a simple code change to do this.

In WebApiConfig.cs change the class implementing IDatabaseInitializer that you pass into Database.SetInitializer from DropCreateDatabaseIfModelChanges to DropCreateDatabaseAlways

Example

Previous (only updated if DataObject schema changes):

public static class WebApiConfig{public static void Register()
        {// Use this class to set configuration options for your mobile serviceConfigOptions options = new ConfigOptions();// Use this class to set WebAPI configuration optionsHttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options));// To display errors in the browser during development, uncomment the following
            // line. Comment it out again when you deploy your service for production use.
            // config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;Database.SetInitializer(new MobileService3Initializer());
        }
    }public class MobileService3Initializer : DropCreateDatabaseIfModelChanges<MobileService3Context>
    {protected override void Seed(MobileService3Context context)
        {

Now (always recreates the Database and reseeds):

 

public static class WebApiConfig{public static void Register()
        {// Use this class to set configuration options for your mobile serviceConfigOptions options = new ConfigOptions();// Use this class to set WebAPI configuration optionsHttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options));// To display errors in the browser during development, uncomment the following
            // line. Comment it out again when you deploy your service for production use.
            // config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;Database.SetInitializer(new MobileService3Initializer());
        }
    }public class MobileService3Initializer : DropCreateDatabaseAlways<MobileService3Context>
    {protected override void Seed(MobileService3Context context)
        {

Walkthrough: Attaching an Azure SQL database to your .NET Backend

$
0
0

Overview

I needed to attach an existing Azure SQL database to my .NET Backend.  This will allow me to expose existing data using the Azure Mobile Service I have defined.  This will walk you through the steps I took and get you on your way!

Setup

Create a new Mobile Service or download the starter project from your existing Mobile Service based on the .NET Backend.

My existing Azure SQL database has the following structure the schema is in the dbo schema (you can see this through the Management portal of your Azure SQL Databases and will be used for this example:

image

Details

Get and Build base project

My existing Mobile Service only has the TodoItem table associated with it.

Download the starter project form the Mobile Services Dashboard if you don’t already have a local copy to work with or if this is a brand new project you can create your Mobile Service inside of Visual Studio.

Or you can create an new Mobile Service project and publish it later:

image

Ensure you build your solution at least once to get the appropriate packages

Add Tables from Existing Database

Now we will add the existing database to the Mobile Services project.

Right click on the Models folder in your project and choose ‘Add’, ‘ADO.NET Entity Data Model’

image

You can name it whatever you want but to stay organized, name it the same as your table.

image

Hit ‘OK’ then choose ‘Code First from database’:

image

Hit next and then choose ‘New Connection’

image

Here you need some information from your azure management portal for your database:

image

image

Copy the server information (in my case you can see what I entered).  Ensure you are using SQL authentication and them find your database in the combo box and select it:

image

Hit ‘OK’

This will populate your information.  Select ‘No’ on the radio button about sensitive data and hit ‘Next’:

image

I selected 2 tables under the dbo schema and hit ‘Finish’:

image

This generates Model Files for each of the Tables I have chosen (and that is it).

Next we need to hook these models up to the Database and expose them through a Table Controller.

Create EntityData models

To expose these new Models to the Table Controller, we need to get these into the format the Entity Framework understands.  We will call these ‘Dto’ or ‘DataTableObject’ classes.

Concentrating on one table (StuffToGet) here is the code generated by my previous steps:

Copy Code:
namespace MobileServiceTest.Models
{using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.ComponentModel.DataAnnotations.Schema;using System.Data.Entity.Spatial;

    [Table("StuffToGet")]public partial class StuffToGet{
        [DatabaseGenerated(DatabaseGeneratedOption.None)]public int ID { get; set; }

        [Required]
        [StringLength(50)]public string Name { get; set; }

        [StringLength(15)]public string Description { get; set; }public int? Purchased { get; set; }
    }
}

Right click on the ‘DataObjects’ folder and create a new class with the same name as your Model but append ‘Dto’:

Copy Code:
using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace MobileServiceTest.DataObjects
{public class StuffToGetDto{
    }
}

Then make the following similar modifications to your class to make it an EntiyData derived class (removing the primary ID field and normalizing the types to Mobile Service Friendly types:

Copy Code:
using Microsoft.WindowsAzure.Mobile.Service;using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace MobileServiceTest.DataObjects
{public class StuffToGetDto:EntityData{public string Name { get; set; }public string Description { get; set; }public int? Purchased { get; set; }
    }
}

Now we need a controller for that Dto (DataTableObject)

Create Table controller

Right click on the ‘Controllers’ folder of your solution explorer and choose: ‘Add’, ‘Controller’

image

Select the Mobile Services table controller as pictured:

image

Add the new DataModel you just created and hit the + button to create a new DbContext for the existing AzureSQL db:

image

Hit ‘Add’ and this will create the DbContext and Table Controller for this connection and table.  And hit ‘OK’

Modify the created DbContext

Now remove the DbContext code and make these similar changes (see comments).  In our case the generated file is ExistingAzureSqlContext.cs:

Copy Code:
using System.Data.Entity;using System.Data.Entity.ModelConfiguration.Conventions;using System.Linq;using Microsoft.WindowsAzure.Mobile.Service;using Microsoft.WindowsAzure.Mobile.Service.Tables;namespace MobileServiceTest.Models
{public class ExistingAzureSqlContext : DbContext{// change contructor to take the dbConnection stringpublic ExistingAzureSqlContext(string dbConnectionString) :base(dbConnectionString)
        { 
        }//change model to the Model and not the Dtopublic System.Data.Entity.DbSet<StuffToGet> StuffToGet { get; set; }
    }
}

This database context will be used in the controller code to attach to the Azure SQL table.

Create Utility Code

Now we need some utility code to map between the Model and the Dto.

Right click on the Models folder and create a new class called ‘SimpleMappedEntityDomainManager’ and put this in the file:

Copy Code:
using AutoMapper;using AutoMapper.Impl;using Microsoft.WindowsAzure.Mobile.Service;using Microsoft.WindowsAzure.Mobile.Service.Tables;using System;using System.Collections.Generic;using System.Data.Entity;using System.Linq;using System.Linq.Expressions;using System.Net.Http;using System.Reflection;using System.Threading.Tasks;using System.Web;using System.Web.Http;using System.Web.Http.OData;namespace MobileServiceUtilities.Models
{//Utilities for Hooking up modelspublic static class MySqlFuncs{
        [DbFunction("SqlServer", "STR")]public static string StringConvert(long number)
        {return number.ToString();
        }
        [DbFunction("SqlServer", "LTRIM")]public static string LTRIM(string s)
        {return s == null ? null : s.TrimStart();
        }// Can only be used locally.public static long LongParse(string s)
        {long ret;long.TryParse(s, out ret);return ret;
        }
    }public class SimpleMappedEntityDomainManager<TData, TModel>
        : MappedEntityDomainManager<TData, TModel>where TData : class, ITableData, new()where TModel : class{private Expression<Func<TModel, object>> dbKeyProperty;public SimpleMappedEntityDomainManager(DbContext context,HttpRequestMessage request, ApiServices services,Expression<Func<TModel, object>> dbKeyProperty)
            : base(context, request, services)
        {this.dbKeyProperty = dbKeyProperty;
        }public override SingleResult<TData> Lookup(string id)
        {return this.LookupEntity(GeneratePredicate(id));
        }public override async Task<TData> UpdateAsync(string id, Delta<TData> patch)
        {return await this.UpdateEntityAsync(patch, ConvertId(id));
        }public override Task<bool> DeleteAsync(string id)
        {return this.DeleteItemAsync(ConvertId(id));
        }private static Expression<Func<TModel, bool>> GeneratePredicate(string id)
        {var m = Mapper.FindTypeMapFor<TModel, TData>();var pmForId = m.GetExistingPropertyMapFor(new PropertyAccessor(typeof(TData).GetProperty("Id")));var keyString = pmForId.CustomExpression;var predicate = Expression.Lambda<Func<TModel, bool>>(Expression.Equal(keyString.Body, Expression.Constant(id)),
                keyString.Parameters[0]);return predicate;
        }private object ConvertId(string id)
        {var m = Mapper.FindTypeMapFor<TData, TModel>();var keyPropertyAccessor = GetPropertyAccessor(this.dbKeyProperty);var pmForId = m.GetExistingPropertyMapFor(new PropertyAccessor(keyPropertyAccessor));
            TData tmp = new TData() { Id = id };var convertedId = pmForId.CustomExpression.Compile().DynamicInvoke(tmp);return convertedId;
        }private PropertyInfo GetPropertyAccessor(Expression exp)
        {if (exp.NodeType == ExpressionType.Lambda)
            {var lambda = exp as LambdaExpression;return GetPropertyAccessor(lambda.Body);
            }else if (exp.NodeType == ExpressionType.Convert)
            {var convert = exp as UnaryExpression;return GetPropertyAccessor(convert.Operand);
            }else if (exp.NodeType == ExpressionType.MemberAccess)
            {var propExp = exp as System.Linq.Expressions.MemberExpression;return propExp.Member as PropertyInfo;
            }else{throw new InvalidOperationException("Unexpected expression node type: " + exp.NodeType);
            }
        }
    }
}

Modify Controller code to use new mapper

Modify the Controller code you just generated as follows and ensure you add this reference to the top (see comments):
using MobileServiceUtilities.Models;
Copy Code:
public class StuffToGetDtoController : TableController<StuffToGetDto>
    {protected override void Initialize(HttpControllerContext controllerContext)
        {base.Initialize(controllerContext);//modify the context to use the constructor that will take a connection string - stored in web.configExistingAzureSqlContext context = new ExistingAzureSqlContext(Services.Settings["ExistingDbConnectionString"]);// DomainManager = new EntityDomainManager<StuffToGetDto>(context, Request, Services);
            // set DomainManger to a new one that we createdDomainManager = new SimpleMappedEntityDomainManager<StuffToGetDto, StuffToGet>(
              context,
              Request,
              Services,
              stuffToGet => stuffToGet.ID );

        }

Map the Id field in the Dto to the ID field in the Model

Finally we need to map between the Dto and Model objects.  In this case the integer ‘ID’ field in the model has to map to the Mobile Service friendly ‘Id’ field which is a string. 

Open WebApiConfig.cs in the App_Start folder and add this code to the end of the Register function:

Copy Code:
    AutoMapper.Mapper.Initialize(cfg =>
            {// Mapping from database type to client typecfg.CreateMap<StuffToGet, StuffToGetDto>()
                    .ForMember(dst => dst.Id, map => map.MapFrom(src => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(src.ID))));// Mapping from client type to database typecfg.CreateMap<StuffToGetDto, StuffToGet>()
                    .ForMember(dst => dst.ID, map => map.MapFrom(src => MySqlFuncs.LongParse(src.Id)));

            });

Add Connection String to Web.Config

The connection string specified in the DbContext needs to be added to your WebConfig.

You can get this string from your Azure SQL Management dashboard:

image

Copy the ADO.NET one:

image

Open your Web.Config and add the key ‘ExistingDbConnectionString’ and the value is this connection string, ensuring you put your password in the section that says {your_password_here}

Copy Code:
<appSettings><!-- Service Bus specific app setings for messaging connections --><add key="PreserveLoginUrl" value="true" /><!-- Use these settings for local development. After publishing to 
    Mobile Services, these settings will be overridden by the values specified
    in the portal. --><add key="ExistingDbConnectionString" value="Server=tcp:nagog6s9ep.database.windows.net,1433;Database=dbForJason;User ID=dbadmin@nagog6s9ep;Password=mypassword;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"/><add key="MS_MobileServiceName" value="MobileServiceTest" />

Build

Finally, build the solution.  Resolve and missing ‘using’ statements by right clicking on them and choosing ‘Resolve’

Test

Now you can run this solution local and test in IE.

Hit the ‘Try it’ button in IE and try to POST, GET and PATCH data into your Azure DB through the Mobile service!

Now, How about adding additional tables?

Easy!

Add Additional Tables from database

We included a 2nd table when we go the StuffToGet table.  Let’s now add Table2 as well since we included the model when we got the first table.

Go through the same steps above:

Add the Dto class:

using Microsoft.WindowsAzure.Mobile.Service;using System;using System.Collections.Generic;using System.Linq;using System.Web;namespace MobileServiceTest.DataObjects
{public class Table2Dto:EntityData{public string Column1 { get; set; }public string Column2 { get; set; }
    }
}

Create Table controller

This is where it will get a little weird.  In this step do NOT create a new dbContext.  Instead select the existing one (note that the new one does not show up).

Add a table controller and use the existing dbContext :

image

Now open that db context (MobileServicesTestContext) and remove the table from that:

   }//REMOVE this 
        //public System.Data.Entity.DbSet<MobileServiceTest.DataObjects.Table2Dto> Table2Dto { get; set; }}

And add this into ExistingAzureSqlContext.cs under the other table definition:

//change model to the Model and not the Dtopublic System.Data.Entity.DbSet<StuffToGet> StuffToGet { get; set; }public System.Data.Entity.DbSet<Table2> Table2 { get; set; }
    }

Like before modify the Controller to use the ExistingAzureSqlContext:

protected override void Initialize(HttpControllerContext controllerContext)
        {base.Initialize(controllerContext);ExistingAzureSqlContext context = new ExistingAzureSqlContext(Services.Settings["ExistingDbConnectionString"]);// DomainManager = new EntityDomainManager<StuffToGetDto>(context, Request, Services);
            // set DomainManger to a new one that we will createDomainManager = new SimpleMappedEntityDomainManager<Table2Dto, Table2>(
              context,
              Request,
              Services,
              table2 => table2.ID);
        }

Map the Id field in the Dto to the ID field in the Model

And add the automapper information:

  AutoMapper.Mapper.Initialize(cfg =>
            {// Mapping from database type to client typecfg.CreateMap<StuffToGet, StuffToGetDto>()
                    .ForMember(dst => dst.Id, map => map.MapFrom(src => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(src.ID))));// Mapping from client type to database typecfg.CreateMap<StuffToGetDto, StuffToGet>()
                    .ForMember(dst => dst.ID, map => map.MapFrom(src => MySqlFuncs.LongParse(src.Id)));// Mapping from database type to client typecfg.CreateMap<Table2, Table2Dto>()
                    .ForMember(dst => dst.Id, map => map.MapFrom(src => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(src.ID))));// Mapping from client type to database typecfg.CreateMap<Table2Dto, Table2>()
                    .ForMember(dst => dst.ID, map => map.MapFrom(src => MySqlFuncs.LongParse(src.Id)));

            
            });

Build

Run and test!

Conclusion

Once you run through this you should be able to see how you can easily bring your own DB to you Mobile Service .NET Backend.  You can do some cool stuff with the Mapper as well so check out the links below.

Let me know if this was useful to you! 

Follow me @jsandersrocks and my team at @WSDevSol on Twitter.

More information

Rename the table exposed by the controller:

  You can rename the Controller to change the public facing name of the table.

So if you want StuffToGetDto to be exposed as StuffToGet, simply rename the class in the file it is defined:

/ old name public class StuffToGetDtoController : TableController<StuffToGetDto>
        //new name of controller without Dto suffixpublic class StuffToGetController : TableController<StuffToGetDto>
    {
Build Mobile Services .NET Backend with no Azure Subscription:

If you don't have an Azure account you can still play with this.  From Visual Studio select the ‘Windows Azure Mobile Service’ template under the ‘Visual C#’, ‘Cloud’ templates when you create a new project

Other links:

Bring Your Own Database with the .NET Backend

Mapping between Database Types and Client Types in the .NET Backend using AutoMapper.

Tables with Integer Keys and the .NET Backend.

Cannot upload xap error: 2004

$
0
0

Just a quicky post…

This is only ONE reason you may have gotten this error and I wanted to share this.  If this does not solve your issue engage the forums or get assisted support from your developer dashboard.

I had a customer that was getting this error when uploading his xap file:  error: 2004:  Something’s happened, and we’re not quite sure what. We haven’t lost any of your app’s info, so try resubmitting again.

Cause:  .NET Reactor version 4.8 bug

Resolution: Remove the "Inject Invalid Metadata” setting under Anti-ILDASM, or upgrade to version 4.9 of .NET Reactor (Store app only, phone not fixed)

 

Let me know if this helped!  If it did not hit the MSDM forums or assisted support, both available from your Developer dashboard.  I will not attempt any further troubleshooting from this blog, but if you DO find a resolution that is different from this… Zap a comment and I will add it to the Blog!

Jeff

Charlotte Azure Partner Boot Camp Links for Mobile Services

$
0
0

Azure Mobile Services .NET backend - Found conflicts between different versions of the same dependent assembly

$
0
0

If you get an error similar to this:
Changed service health to 'Critical' (Service is unhealthy. Please check the service logs to determine the issue and how to correct it.)

And you check the logs in your dashboard and see similar to this:
Found conflicts between different versions of the same dependent assembly 'Microsoft.WindowsAzure.Storage': 4.2.1.0. Please change your project to use version '3.1.0.1' which is the one currently supported by the hosting environment.

The log tells you what the resolution is (use the correct supported version of the package).

There are a few ways you can get yourself into this situation but lets just fix the issue shall we?

There are a ton of dependencies between packages you may add and the ones that are added by default.  The easiest way to get out of this mess is to identify and find the correct version of the conflict so you can install it, and also reset all the other packages to their default and supported configuration.

How do you get the default configuration?

Easy!   Backup the entire project somewhere (are you using VSO or something cool like that.. it makes it easy).  Create a new Cloud app in Mobile Services (or download the starter project from your dashboard) and use the packages.config file to compare to your project’s packages.config file (don’t forget to backup the entire project somewhere first).  Then you can compare your broken packages.config with the default one and fix up the references… and remove the offending package.  Sometimes it is easiest to replace your old config file with this new one and add back missing references identified by the build environment.

Finally add the correct version back.  In this case open the package manager console <Tools> <NuGet Package Manager> <Package Manager Console> and type:  Install-Package WindowsAzure.Storage -Version 3.1.0.1

Clean the Build.  Then Build.  When you build it will update the dependent references correctly.  If you have added other references to your project be sure to add them back as well.

Then when you publish, Ensure you choose the option to replace all the destination files.

Let me know if this helps you!

Always Drop and Create Local Database .NET Backend for Azure Mobile Services

$
0
0

In my early testing I wanted to always seed my Local Database.  By default the db was only dropped and reseeded if you changed the models.  There is a simple code change to do this.

In WebApiConfig.cs change the class implementing IDatabaseInitializer that you pass into Database.SetInitializer from DropCreateDatabaseIfModelChanges to DropCreateDatabaseAlways

Example

Previous (only updated if DataObject schema changes):

    public static class WebApiConfig
    {
        public static void Register()
        {
            // Use this class to set configuration options for your mobile service
            ConfigOptions options = new ConfigOptions();

            // Use this class to set WebAPI configuration options
            HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options));

            // To display errors in the browser during development, uncomment the following
            // line. Comment it out again when you deploy your service for production use.
            // config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;

            Database.SetInitializer(new MobileService3Initializer());
        }
    }

    public class MobileService3Initializer : DropCreateDatabaseIfModelChanges<MobileService3Context>
    {
        protected override void Seed(MobileService3Context context)
        {
            

Now (always recreates the Database and reseeds):

 

   public static class WebApiConfig
    {
        public static void Register()
        {
            // Use this class to set configuration options for your mobile service
            ConfigOptions options = new ConfigOptions();

            // Use this class to set WebAPI configuration options
            HttpConfiguration config = ServiceConfig.Initialize(new ConfigBuilder(options));

            // To display errors in the browser during development, uncomment the following
            // line. Comment it out again when you deploy your service for production use.
            // config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;

            Database.SetInitializer(new MobileService3Initializer());
        }
    }

    public class MobileService3Initializer : DropCreateDatabaseAlways<MobileService3Context>
    {
        protected override void Seed(MobileService3Context context)
        {


Walkthrough: Attaching an Azure SQL database to your .NET Backend

$
0
0


Overview

I needed to attach an existing Azure SQL database to my .NET Backend.  This will allow me to expose existing data using the Azure Mobile Service I have defined.  This will walk you through the steps I took and get you on your way!

Setup

Create a new Mobile Service or download the starter project from your existing Mobile Service based on the .NET Backend.

My existing Azure SQL database has the following structure the schema is in the dbo schema (you can see this through the Management portal of your Azure SQL Databases and will be used for this example:

image

Details

Get and Build base project

My existing Mobile Service only has the TodoItem table associated with it.

Download the starter project form the Mobile Services Dashboard if you don’t already have a local copy to work with or if this is a brand new project you can create your Mobile Service inside of Visual Studio.

Or you can create an new Mobile Service project and publish it later:

image

Ensure you build your solution at least once to get the appropriate packages

Add Tables from Existing Database

Now we will add the existing database to the Mobile Services project.

Right click on the Models folder in your project and choose ‘Add’, ‘ADO.NET Entity Data Model’

image

You can name it whatever you want but to stay organized, name it the same as your table.

image

Hit ‘OK’ then choose ‘Code First from database’:

image

Hit next and then choose ‘New Connection’

image

Here you need some information from your azure management portal for your database:

image

image

Copy the server information (in my case you can see what I entered).  Ensure you are using SQL authentication and them find your database in the combo box and select it:

image

Hit ‘OK’

This will populate your information.  Select ‘No’ on the radio button about sensitive data and hit ‘Next’:

image

I selected 2 tables under the dbo schema and hit ‘Finish’:

image

This generates Model Files for each of the Tables I have chosen (and that is it).

Next we need to hook these models up to the Database and expose them through a Table Controller.

Create EntityData models

To expose these new Models to the Table Controller, we need to get these into the format the Entity Framework understands.  We will call these ‘Dto’ or ‘DataTableObject’ classes.

Concentrating on one table (StuffToGet) here is the code generated by my previous steps:

Copy Code:

namespace MobileServiceTest.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;

    [Table("StuffToGet")]
    public partial class StuffToGet
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int ID { get; set; }

        [Required]
        [StringLength(50)]
        public string Name { get; set; }

        [StringLength(15)]
        public string Description { get; set; }

        public int? Purchased { get; set; }
    }
}

Right click on the ‘DataObjects’ folder and create a new class with the same name as your Model but append ‘Dto’:

Copy Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MobileServiceTest.DataObjects
{
    public class StuffToGetDto
    {
    }
}

Then make the following similar modifications to your class to make it an EntiyData derived class (removing the primary ID field and normalizing the types to Mobile Service Friendly types:

Copy Code:

using Microsoft.WindowsAzure.Mobile.Service;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MobileServiceTest.DataObjects
{
    public class StuffToGetDto:EntityData
    {
        public string Name { get; set; }

        public string Description { get; set; }

        public int? Purchased { get; set; }
    }
}

Now we need a controller for that Dto (DataTableObject)

Create Table controller

Right click on the ‘Controllers’ folder of your solution explorer and choose: ‘Add’, ‘Controller’

image

Select the Mobile Services table controller as pictured:

image

Add the new DataModel you just created and hit the + button to create a new DbContext for the existing AzureSQL db:

image

Hit ‘Add’ and this will create the DbContext and Table Controller for this connection and table.  And hit ‘OK’

Modify the created DbContext

Now remove the DbContext code and make these similar changes (see comments).  In our case the generated file is ExistingAzureSqlContext.cs:

Copy Code:

using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using Microsoft.WindowsAzure.Mobile.Service;
using Microsoft.WindowsAzure.Mobile.Service.Tables;

namespace MobileServiceTest.Models
{
    public class ExistingAzureSqlContext : DbContext
    {

        // change contructor to take the dbConnection string
        public ExistingAzureSqlContext(string dbConnectionString) :
            base(dbConnectionString)
        {

        }

        //change model to the Model and not the Dto
        public System.Data.Entity.DbSet<StuffToGet> StuffToGet { get; set; }
    }
}

This database context will be used in the controller code to attach to the Azure SQL table.

Create Utility Code

Now we need some utility code to map between the Model and the Dto.

Right click on the Models folder and create a new class called ‘SimpleMappedEntityDomainManager’ and put this in the file:

Copy Code:

using AutoMapper;
using AutoMapper.Impl;
using Microsoft.WindowsAzure.Mobile.Service;
using Microsoft.WindowsAzure.Mobile.Service.Tables;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using System.Reflection;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.OData;

namespace MobileServiceUtilities.Models
{

    //Utilities for Hooking up models
    public static class MySqlFuncs
    {
        [DbFunction("SqlServer", "STR")]
        public static string StringConvert(long number)
        {
            return number.ToString();
        }
        [DbFunction("SqlServer", "LTRIM")]
        public static string LTRIM(string s)
        {
            return s == null ? null : s.TrimStart();
        }
        // Can only be used locally.
        public static long LongParse(string s)
        {
            long ret;
            long.TryParse(s, out ret);
            return ret;
        }
    }

    public class SimpleMappedEntityDomainManager<TData, TModel>
        : MappedEntityDomainManager<TData, TModel>
        where TData : class, ITableData, new()
        where TModel : class
    {
        private Expression<Func<TModel, object>> dbKeyProperty;

        public SimpleMappedEntityDomainManager(DbContext context,
            HttpRequestMessage request, ApiServices services,
            Expression<Func<TModel, object>> dbKeyProperty)
            : base(context, request, services)
        {
            this.dbKeyProperty = dbKeyProperty;
        }
        public override SingleResult<TData> Lookup(string id)
        {
            return this.LookupEntity(GeneratePredicate(id));
        }
        public override async Task<TData> UpdateAsync(string id, Delta<TData> patch)
        {
            return await this.UpdateEntityAsync(patch, ConvertId(id));
        }
        public override Task<bool> DeleteAsync(string id)
        {
            return this.DeleteItemAsync(ConvertId(id));
        }

        private static Expression<Func<TModel, bool>> GeneratePredicate(string id)
        {
            var m = Mapper.FindTypeMapFor<TModel, TData>();
            var pmForId = m.GetExistingPropertyMapFor(new PropertyAccessor(typeof(TData).GetProperty("Id")));
            var keyString = pmForId.CustomExpression;
            var predicate = Expression.Lambda<Func<TModel, bool>>(
                Expression.Equal(keyString.Body, Expression.Constant(id)),
                keyString.Parameters[0]);
            return predicate;
        }

        private object ConvertId(string id)
        {
            var m = Mapper.FindTypeMapFor<TData, TModel>();
            var keyPropertyAccessor = GetPropertyAccessor(this.dbKeyProperty);
            var pmForId = m.GetExistingPropertyMapFor(new PropertyAccessor(keyPropertyAccessor));
            TData tmp = new TData() { Id = id };
            var convertedId = pmForId.CustomExpression.Compile().DynamicInvoke(tmp);
            return convertedId;
        }

        private PropertyInfo GetPropertyAccessor(Expression exp)
        {
            if (exp.NodeType == ExpressionType.Lambda)
            {
                var lambda = exp as LambdaExpression;
                return GetPropertyAccessor(lambda.Body);
            }
            else if (exp.NodeType == ExpressionType.Convert)
            {
                var convert = exp as UnaryExpression;
                return GetPropertyAccessor(convert.Operand);
            }
            else if (exp.NodeType == ExpressionType.MemberAccess)
            {
                var propExp = exp as System.Linq.Expressions.MemberExpression;
                return propExp.Member as PropertyInfo;
            }
            else
            {
                throw new InvalidOperationException("Unexpected expression node type: " + exp.NodeType);
            }
        }
    }
}

Modify Controller code to use new mapper

Modify the Controller code you just generated as follows and ensure you add this reference to the top (see comments):
using MobileServiceUtilities.Models;

Copy Code:

 public class StuffToGetDtoController : TableController<StuffToGetDto>
    {
        protected override void Initialize(HttpControllerContext controllerContext)
        {
            base.Initialize(controllerContext);
            //modify the context to use the constructor that will take a connection string - stored in web.config
            ExistingAzureSqlContext context = new ExistingAzureSqlContext(Services.Settings["ExistingDbConnectionString"]);

            // DomainManager = new EntityDomainManager<StuffToGetDto>(context, Request, Services);
            // set DomainManger to a new one that we created
            DomainManager = new SimpleMappedEntityDomainManager<StuffToGetDto, StuffToGet>(
              context,
              Request,
              Services,
              stuffToGet => stuffToGet.ID );

        }

Map the Id field in the Dto to the ID field in the Model

Finally we need to map between the Dto and Model objects.  In this case the integer ‘ID’ field in the model has to map to the Mobile Service friendly ‘Id’ field which is a string. 

Open WebApiConfig.cs in the App_Start folder and add this code to the end of the Register function:

Copy Code:

    AutoMapper.Mapper.Initialize(cfg =>
            {
                // Mapping from database type to client type
                cfg.CreateMap<StuffToGet, StuffToGetDto>()
                    .ForMember(dst => dst.Id, map => map.MapFrom(src => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(src.ID))));
                // Mapping from client type to database type
                cfg.CreateMap<StuffToGetDto, StuffToGet>()
                    .ForMember(dst => dst.ID, map => map.MapFrom(src => MySqlFuncs.LongParse(src.Id)));

            });

Add Connection String to Web.Config

The connection string specified in the DbContext needs to be added to your WebConfig.

You can get this string from your Azure SQL Management dashboard:

image

Copy the ADO.NET one:

image

Open your Web.Config and add the key ‘ExistingDbConnectionString’ and the value is this connection string, ensuring you put your password in the section that says {your_password_here}

Copy Code:

 <appSettings>
    <!-- Service Bus specific app setings for messaging connections -->
    <add key="PreserveLoginUrl" value="true" />
    <!-- Use these settings for local development. After publishing to
    Mobile Services, these settings will be overridden by the values specified
    in the portal. -->
    <add key="ExistingDbConnectionString" value="Server=tcp:nagog6s9ep.database.windows.net,1433;Database=dbForJason;User ID=dbadmin@nagog6s9ep;Password=mypassword;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;"/>
    <add key="MS_MobileServiceName" value="MobileServiceTest" />
 

Build

Finally, build the solution.  Resolve and missing ‘using’ statements by right clicking on them and choosing ‘Resolve’

Test

Now you can run this solution local and test in IE.

Hit the ‘Try it’ button in IE and try to POST, GET and PATCH data into your Azure DB through the Mobile service!

Now, How about adding additional tables?

Easy!

Add Additional Tables from database

We included a 2nd table when we go the StuffToGet table.  Let’s now add Table2 as well since we included the model when we got the first table.

Go through the same steps above:

Add the Dto class:

using Microsoft.WindowsAzure.Mobile.Service;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MobileServiceTest.DataObjects
{
    public class Table2Dto:EntityData
    {

            public string Column1 { get; set; }

            public string Column2 { get; set; }

    }
}

Create Table controller

This is where it will get a little weird.  In this step do NOT create a new dbContext.  Instead select the existing one (note that the new one does not show up).

Add a table controller and use the existing dbContext :

image

Now open that db context (MobileServicesTestContext) and remove the table from that:

   }

     //REMOVE this
        //public System.Data.Entity.DbSet<MobileServiceTest.DataObjects.Table2Dto> Table2Dto { get; set; }
    }

And add this into ExistingAzureSqlContext.cs under the other table definition:

   //change model to the Model and not the Dto
        public System.Data.Entity.DbSet<StuffToGet> StuffToGet { get; set; }

        public System.Data.Entity.DbSet<Table2> Table2 { get; set; }
    }

Like before modify the Controller to use the ExistingAzureSqlContext:

 protected override void Initialize(HttpControllerContext controllerContext)
        {
            base.Initialize(controllerContext);
            ExistingAzureSqlContext context = new ExistingAzureSqlContext(Services.Settings["ExistingDbConnectionString"]);

            // DomainManager = new EntityDomainManager<StuffToGetDto>(context, Request, Services);
            // set DomainManger to a new one that we will create
            DomainManager = new SimpleMappedEntityDomainManager<Table2Dto, Table2>(
              context,
              Request,
              Services,
              table2 => table2.ID);
        }

Map the Id field in the Dto to the ID field in the Model

And add the automapper information:

  AutoMapper.Mapper.Initialize(cfg =>
            {
                // Mapping from database type to client type
                cfg.CreateMap<StuffToGet, StuffToGetDto>()
                    .ForMember(dst => dst.Id, map => map.MapFrom(src => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(src.ID))));
                // Mapping from client type to database type
                cfg.CreateMap<StuffToGetDto, StuffToGet>()
                    .ForMember(dst => dst.ID, map => map.MapFrom(src => MySqlFuncs.LongParse(src.Id)));

                // Mapping from database type to client type
                cfg.CreateMap<Table2, Table2Dto>()
                    .ForMember(dst => dst.Id, map => map.MapFrom(src => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(src.ID))));
                // Mapping from client type to database type
                cfg.CreateMap<Table2Dto, Table2>()
                    .ForMember(dst => dst.ID, map => map.MapFrom(src => MySqlFuncs.LongParse(src.Id)));


            });

Build

Run and test!

Conclusion

Once you run through this you should be able to see how you can easily bring your own DB to you Mobile Service .NET Backend.  You can do some cool stuff with the Mapper as well so check out the links below.

Let me know if this was useful to you! 

Follow me @jsandersrocks and my team at @WSDevSol on Twitter.

More information

Rename the table exposed by the controller:

  You can rename the Controller to change the public facing name of the table.

So if you want StuffToGetDto to be exposed as StuffToGet, simply rename the class in the file it is defined:

/ old name public class StuffToGetDtoController : TableController<StuffToGetDto>
        //new name of controller without Dto suffix
    public class StuffToGetController : TableController<StuffToGetDto>
    {
    

Build Mobile Services .NET Backend with no Azure Subscription:

If you don’t have an Azure account you can still play with this.  From Visual Studio select the ‘Windows Azure Mobile Service’ template under the ‘Visual C#’, ‘Cloud’ templates when you create a new project

Other links:

Bring Your Own Database with the .NET Backend

Mapping between Database Types and Client Types in the .NET Backend using AutoMapper.

Tables with Integer Keys and the .NET Backend.

Cannot upload xap error: 2004

$
0
0

Just a quicky post…

This is only ONE reason you may have gotten this error and I wanted to share this.  If this does not solve your issue engage the forums or get assisted support from your developer dashboard.

I had a customer that was getting this error when uploading his xap file:  error: 2004:  Something’s happened, and we’re not quite sure what. We haven’t lost any of your app’s info, so try resubmitting again.

Cause:  .NET Reactor version 4.8 bug

Resolution: Remove the "Inject Invalid Metadata” setting under Anti-ILDASM, or upgrade to version 4.9 of .NET Reactor (Store app only, phone not fixed)

 

Let me know if this helped!  If it did not hit the MSDM forums or assisted support, both available from your Developer dashboard.  I will not attempt any further troubleshooting from this blog, but if you DO find a resolution that is different from this… Zap a comment and I will add it to the Blog!

Jeff

Charlotte Azure Partner Boot Camp Links for Mobile Services

$
0
0

Azure Mobile Services .NET backend – Found conflicts between different versions of the same dependent assembly

$
0
0

If you get an error similar to this:
Changed service health to ‘Critical’ (Service is unhealthy. Please check the service logs to determine the issue and how to correct it.)

And you check the logs in your dashboard and see similar to this:
Found conflicts between different versions of the same dependent assembly ‘Microsoft.WindowsAzure.Storage': 4.2.1.0. Please change your project to use version ‘3.1.0.1’ which is the one currently supported by the hosting environment.

The log tells you what the resolution is (use the correct supported version of the package).

There are a few ways you can get yourself into this situation but lets just fix the issue shall we?

There are a ton of dependencies between packages you may add and the ones that are added by default.  The easiest way to get out of this mess is to identify and find the correct version of the conflict so you can install it, and also reset all the other packages to their default and supported configuration.

How do you get the default configuration?

Easy!   Backup the entire project somewhere (are you using VSO or something cool like that.. it makes it easy).  Create a new Cloud app in Mobile Services (or download the starter project from your dashboard) and use the packages.config file to compare to your project’s packages.config file (don’t forget to backup the entire project somewhere first).  Then you can compare your broken packages.config with the default one and fix up the references… and remove the offending package.  Sometimes it is easiest to replace your old config file with this new one and add back missing references identified by the build environment.

Finally add the correct version back.  In this case open the package manager console <Tools> <NuGet Package Manager> <Package Manager Console> and type:  Install-Package WindowsAzure.Storage -Version 3.1.0.1

Clean the Build.  Then Build.  When you build it will update the dependent references correctly.  If you have added other references to your project be sure to add them back as well.

Then when you publish, Ensure you choose the option to replace all the destination files.

Let me know if this helps you!

Remove ‘Server’ and ‘X-Powered-By’ headers from your Azure Mobile Apps

$
0
0

Knowing the server type and what it is running can be information that an attacker may leverage.  This article explains how you can remove the subject headers.

Azure Mobile Apps are really Azure Web Apps.  You can configure the headers by altering the Web.Config just like you would with a standard ASP.Net application!

Problem

Here is an example of the headers returned from a simple Azure Mobile App (replace contosomobileapp with the name of your Mobile app):

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 422
Content-Type: application/json; charset=utf-8
Expires: 0
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=df41f72d5dafaca237feeeb4df546bb62b24197ead56d3e53c2496c1f90fe094;Path=/;Domain=contosomobileapp.azurewebsites.net
Date: Wed, 07 Oct 2015 13:13:57 GMT

Solution

Open the site Web.Config in your Visual Studio project and find the <system.webServer> section

snip_20151007093103

Add these two sections inside this section:

Copy Code:

    <security>
      <requestFiltering removeServerHeader ="true"></requestFiltering>
    </security>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By"/>
      </customHeaders>
    </httpProtocol>

So the final Web.Config section will look something like this:

snip_20151007095619

(you can ignore the squiggle under removeServerHeader)

Now right mouse click on the Web.Config in your Solution Explorer view and choose publish:

Untitled

Result

The headers are removed:

HTTP/1.1 200 OK

Cache-Control: no-cache

Pragma: no-cache

Content-Length: 422

Content-Type: application/json; charset=utf-8

Expires: 0

Set-Cookie: ARRAffinity=df41f72d5dafaca237feeeb4df546bb62b24197ead56d3e53c2496c1f90fe094;Path=/;Domain=contosomobileapp.azurewebsites.net

Date: Wed, 07 Oct 2015 13:19:07 GMT

Conclusion

As you can see Azure Mobile Apps are really Azure Web Sites with some additional code to access and present data.  You can easily configure your Azure Mobile App using the Web.Config like you would for an ASP.Net app deployed on Azure Web Sites.

Let me know if this was a help to you!

Ref: https://azure.microsoft.com/en-us/blog/removing-standard-server-headers-on-windows-azure-web-sites/

Viewing all 140 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>