12/27/15

API OAuth Token Access-Control-Allow-Credentials header is empty

When implementing an Azure API App using MVC Web API with OAuth Bearer Token Authorization, we came across this error:


Response to preflight request doesn't pass access control check: Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'http://domain.com' is therefore not allowed access.


This error is a result of an AJAX request to an Azure API App with Cross-origin resource sharing (CORS) support. We looked at the response headers and noticed that the 'Access-Control-Allow-Credentials header was actually blank which does not allow the browser to continue since it is a security policy. The code that makes the request is shown next:


$.ajax({
                type: 'POST',  async:true,
                url: 'https://someapp.azurewebsites.net/token',
                dataType: "json",
                contentType: 'application/x-www-form-urlencoded; charset=utf-8',
                xhrFields: {
                    withCredentials: true
                },
                headers: {
                    'Authorization': 'Basic ' + appInfo                   
                },             
                success: function (result) {
                    var token = result.access_token;
                    //…                  
                },
                error: function (req, status, error) {
                    if (typeof(req) != 'undefined') {
                        var msg = status || req.responseJSON.error;
                        //…
                    }                  
                }
        });


The same code works OK when testing on the test environment (NO Azure). We can see how the headers for cross domain and credentials are included in the response headers. This confirms that outside of Azure, the CORS configuration in the application is correct.


Response Headers

Access-Control-Allow-Headers
Access-Control-Allow-Origin
Access-Control-Allow-Credentials


In Azure, we need to configure the CORS settings on the Azure Management UI which overrides any application CORS settings. This configuration outside of our web API application causes this problem with the header.

Since we are using OAuth bearer token security, we pass the client information as a header, and we do not use any type of cookies for security. This means that we do not need to use the withCredentials AJAX parameter.


withCredentials

Standard CORS requests do not send or set any cookies by default. In order to include cookies as part of the request, you need to set the XMLHttpRequest’s .withCredentials property to true. The server must also enable credentials by setting the Access-Control-Allow-Credentials response header to "true"


Once the withCredentials parameter is removed from the AJAX request, the Azure API App started to work properly. This is how the code looks now:


$.ajax({
                type: 'POST',  async:true,
                url: 'https://someapp.azurewebsites.net/token',                
                dataType: "json",
                contentType: 'application/x-www-form-urlencoded; charset=utf-8',
                //xhrFields: {
                //    withCredentials: true
                //},
                headers: {
                    'Authorization': 'Basic ' + appInfo                   
                },             
                success: function (result) {
                    var token = result.access_token;
                    //…                  
                },
                error: function (req, status, error) {
                    if (typeof(req) != 'undefined') {
                        var msg = status || req.responseJSON.error;
                        //…
                    }                   
                }
            });



The resolution is to configure the request in a way that matches the expected response header from the server. In this case, there was no need to exchange security over cookies since this is done using a token. This is the solution for this particular case, but there could be other root cause that manifest in a similar problem.  

12/13/15

404 Error axd HTTP Handler

This error is common when a previously working web app has been migrated to another server or a cloud hosted environment, and it is now showing the HTTP 404 (Not Found) error.  To figure out the root cause and solution, let’s take a look at how the web app was configured initially. We will then take a look at the solution.

HTTP Handlers Configuration

When we look at the web.config settings we can find this entry:


<system.web>
            
    <httpHandlers>
<add verb="*" path="myhandler.axd"   type="MyHandler"/>
    </httpHandlers>
</system.web>



This setting indicates that there is an HTTP handler defined by the type MyHandler. It also tells IIS to allow all requests (verbs = GET, POST etc.) with the route myhandler.axd as this handler should manage the requests. This is important because this also works as a mime type setting, so there is no need to add a mime type for this file extension on IIS. It is important to notice that this setting only works for IIS 5, 6 and IIS7 Classic Mode.  

If we migrate the app to a hosting service that has IIS7 (*Note that you can even notice this problem running on IIS7 express if you upgrade Visual Studio), we can probably recreate the 404 error.

There are two solutions to this problem:
  1. Use IIS7 Classic Mode
  2. Update the Web.config for IIS7 Support

Use IIS7 Classic Mode

If access to IIS is available, we can just change application pool Managed Pipeline Mode property to Classic, and the handler should be invoked properly. This can also be done for IIS Express by looking at the project properties - Manage Pipeline Mode setting.

Updating Web.config for IIS7 Support

In the case of cloud hosting, we need to make the change in the web.config by adding a new configuration section for HTTP handlers (*Note: This is used for IIS7 and future version). Let’s take a look at how that should look:



<system.webServer>
       <handlers>                
      <add name="myhandler" verb="*" path="myhandler.axd" type="ozkary.MyHandler"   preCondition="integratedMode"/>  
    </handlers>
</system.webServer>



This setting indicates that we have a handler that should manage the requests in integrated mode. This is how HTTP handlers are configured when running on IIS7.  If we deploy again and load the site, we should no longer see the 404 error.

We should notice that these settings can co-exist in the web.config, but only one will be loaded which is dependent on your IIS environment.  This approach can let us develop on previous version of IIS and target more recent version on our deployments.

12/12/15

Publish MVC Web App on Azure Virtual Directory

Azure Web Apps are deployed as a new website on the Azure cloud. For those who have control of the server, this is similar to adding a new website on an IIS server. What if we need to deploy another web app on Azure, but we do not want to create a new web site?  Well the answer is to create a virtual directory and deploy the web app there. Let’s take a look at how we can do that using the Azure management website.  

We start by looking at a Web App that is already deployed on Azure. We need to look at the settings as shown below:

Azure Web App Settings
The image above shows the Virtual application and directories settings. This is the area where we can add a virtual directory that we can later target or use for another deployment. Let’s add a virtual directory named Admin. We will use this for the administration module of the web app. We need to enter the virtual directory name, physical path under wwwroot and check that we want this as an application which we need if we want to allocate the web app to an app pool. We can now save the changes, and the result should look as follows:

Admin Virtual Directory
We are now ready to show how to deploy this. Let's go over Visual Studio, open the solution and take a look at the publishing profile for the original app. Notice the Site Name and Destination URL settings.

Publish Profile Settings
Since we are now deploying to the same web app site and URL, we just need to append the virtual directory information (/Admin) as shown below:


Publish Profile - Virtual Directory

We can now just press the publish button, and we have one Azure web app instance hosting two web apps with one at the wwwroot and the other on the virtual directory off of wwwroot.

I hope this tip provides some insight for your web app deployment strategies on Azure.

11/15/15

SharePoint App List Lookup Delete Behavior

A SharePoint list can have a field type lookup which is a reference to another list. As an example, we have a client and project lists. The project list has a client lookup field which as reference uses the client list. As in any application, we need referential integrity, and we need to prevent the deletion of a reference/parent record by adding a constraint on the lookup field. (see sample project download at the end)


Add a Constraint to a List

In order to add a constraint to a lookup field, we need to open the schema.xml file under the list definition. Unfortunately for us, Visual Studio does not provide all the possible attributes for a list definition, so a manual change to the xml file is required. The schema.xml contains the metadata that defines the list and all the fields. We need to find the field that we need (in our case client) and add the following attributes:

RelationshipDeleteBehavior="Restrict"
Prevent deletes of the reference or parent record when a dependency exists.
Indexed="TRUE"
This field needs to be indexed in order to support a constraint. This field can also be updated from the properties tab.

Attribute Changes:



Features Deployment

Note*: When building SharePoint JavaScript apps using Visual Studio, we need to be familiar of how the features deployment works and how it can affect a list field lookup or relationship constraint.

Now that we have our lists definition and constraint, we need to make sure that dependencies are deployed first. During the deployment of the application, the deployment does not fail if a dependency is not defined first. In our example, the project list depends on the client list to be deployed first. If we deploy the project list first, the client relationship constraint will not be applied to the list, and the parent records could be deleted leaving orphan records. 

In order to prevent this deployment problem, we need to make sure that the features are deployed in the correct order. In our example (see image below), the Application feature (contains the web application artifacts) is defined before our lists. We then define the client and project lists.



By defining the client feature lists (with the client list definition and instance) before the project feature, we make sure that our constraint will be deployed properly. This helps us make sure that on the server data integrity is enforced. The order of the features can be rearranged by opening the package file under the package folder.  This opens an interface that allows us to move features up or down.



Now that we have our list definitions, we could move forward with building a SharePoint AngularJS SPA that shows how this constraint is actually working.  We will do this in another blog entry.

A sample of this project can be found here:  Github


Thanks

11/8/15

AngularJS Minimized File Unknown Provider

We have a working AngularJS single page application (SPA), but the moment we minimized the JS files, the app breaks with an Unknown Provider error.

When facing this problem, we need to look at how we are injecting dependencies into our modules because when minimizing the files, the parameters name will be changed and Angular would not be able to resolve the dependency.

Implicit (bad) Injection Approach

We start by looking at a common way of injecting dependencies which can lead into a problem.
    var app = angular.module('app', []);     
    app.config(appConfig);
    app.run(initApp);
    app.controller('appCtrl', appCtrl);
    
    function appConfig($myProvider) {
        $myProvider.appConfig();
    }

    function initApp(myService) {
        myService.initApp();
    }

    function appCtrl($scope) {
        $scope.appCtrl = 'hi ozkary';
    }

In this example, we are defining a module that has a configuration, app initialization and controller functions. When we define those functions, we are only setting the function names, but the function implementation has a parameter which indicates what needs to be injected. The problem with this approach is that when this code is minimized, it looks as follows:

function i(n){n.appConfig()}
function r(n){n.initApp()}
function u(n){n.appCtrl="hi ozkary"}
var t=n.module("app",[]);
t.config(i);
t.run(r);
t.controller("appCtrl",u)

As we can see, the parameters are renamed to “n” at which point there is probably no dependency with such name, and Angular is not able to find it. This is why we get the ugly Unknown Provider error.

Explicit Injection Declaration

To address this problem, we need to change the way we declare the dependencies using an array as parameter. With this approach, our code changes to this:

    var app = angular.module('app', []);
    app.config(['$myProvider', appConfig]);
    app.run(['myService', initApp]);
    app.controller('appCtrl', ['$scope', appCtrl]);
   
    function appConfig($myProvider) {
        $myProvider.appConfig();
    }

    function initApp(myService) {
        myService.initApp();
    }

    function appCtrl($scope) {
        $scope.appCtrl = 'hi ozkary';
    }

The advantage of this approach that is that the array values are not mangled by the minimization process, and this allows Angular to find and inject the dependency. The minimized version of our code now looks like this:

function i(n){n.appConfig()}
function r(n){n.initApp()}
function u(n){n.appCtrl="hi ozkary"}
var t=n.module("app",[]);
t.config(["$myProvider",i]);
t.run(["myService",r]);
t.controller("appCtrl",["$scope",u])

Yes, the dependency name is kept, and Angular should be able to resolve it. We can also notice that the parameter “n” is still used in the function, but what is important is the name declared on the array.
Moving forward, we should explicitly define our dependencies as minimization of resources is now a must standard.

Hope it helps.

10/24/15

SharePoint 2013 API OData For Lookup Fields

When using SharePoint data lists as the backend for an application, we can leverage the use of REST and OData to fetch the information from a data list. When the list contains lookup fields, a normal GET operation on the list only returns the id from the lookup field which may not be enough for some cases. 

In the case that more information is needed from the lookup or reference field, we can leverage the OData $expand parameter. This parameter is used to expand the related data so that in addition of the id other information also becomes available. As an example, we can look at a simple Project data list which has a lookup field named Client. This field uses the Client list as reference.

Project List Fields (internal names)
Client List Fields (internal names)
id
Id
Name
Name
Client  (lookup to Client)


How to fetch the data:

Note: my.sharepoint.com should be replaced with a specific domain name.


In this URL string, we are using the getbytitle API which allows us to query a list by name. The items route suffix indicates to fetch all the items with no explicit filters (where clause) and all the available fields. The resulting data contains the fields Id, Name, ClientId (where is this coming from?) and other fields that are created by the SharePoint platform.  For our purposes, our focus is only on our custom fields (Name, ClientId)


We can notice that there is a ClientId field, but the field that we defined is named Client. SharePoint by default returns the lookup field id using this format: field name + id. In this case, the name is ClientId which as we can guess is the id of the client record.

What about also getting the client name?

In the case that more lookup data is required as in the case of client name, we must use a couple of OData parameters to expand on the selection of the look up fields: $select, $expand

Parameter
Description
$select
Use this parameter to control what fields should be selected.
$expand
Use this field to indicate what lookup field should be expanded to get additional information from that field. Field to expand must be in the $select parameter.


As an example, our request can be changed to this: (no domain name listed)

_api/web/lists/getbytitle('project')/items?$select=Client/Name,ClientId,Name,Id&$expand=Client

URL Segments:

URL Segment
Description
_api/web/lists/getbytitle('project')/items
This is the API and route to query a list by name and retrieve the items (records)
$select=Client/Name,ClientId,Name,Id
OData request parameter to select fields by name

$expand=Client
OData request parameter to indicate what look up field should be expanded to get additional information.

When using the $expand query parameter, the $select query parameter must also be used, and the field to be expanded must be explicitly declared as shown on our example above. The result of this request returns the project name and id as well as client name and client id.  We should note the format used to get the client name, Client/Name. This format is what indicates that we want the Name field from the Client list.

Sample Result:

A sample of the response is shown below. The results array contains each record, for which we can find the selected fields as well as the client property (object) with the name property (client name).

Expanded Results:


As shown above, the USE of OData request parameters are very important when there is a need to get related/lookup data with one request.