Tuesday, October 1, 2024

APIM policy to get the token and send request in backend

   <backend>

        <retry condition="@(context.Response.StatusCode == 401)" count="2" interval="1" first-fast-retry="true">
            <choose>
                <when condition="@(context.Variables.GetValueOrDefault("calledOnce", false))">
                    <cache-remove-value key="token" />
                </when>
            </choose>
            <!-- Get token -->
            <cache-lookup-value key="token" default-value="noToken" variable-name="token" />
            <!-- Retrieve token if needed -->
            <choose>
                <when condition="@((string)context.Variables["token"] == "noToken")">
                    <set-variable name="clientSecret" value="@(System.Net.WebUtility.UrlEncode("{{concur-clientsecret}}"))" />
                    <!-- Retrieve token -->
                    <send-request ignore-error="false" timeout="20" response-variable-name="tokenResponse" mode="new">
                        <set-url>@($"{{concur-url}}/oauth2/v0/token")</set-url>
                        <set-method>POST</set-method>
                        <set-header name="Content-Type" exists-action="override">
                            <value>application/x-www-form-urlencoded</value>
                        </set-header>
                        <set-body>@($"grant_type=refresh_token&client_id={{concur-clientid}}&client_secret={(string)context.Variables["clientSecret"]}&refresh_token={{concur-refresh-token}}")</set-body>
                    </send-request>
                    <!-- Cache token -->
                    <set-variable name="response" value="@(((IResponse)context.Variables["tokenResponse"]).Body.As<JObject>())" />
                    <set-variable name="token" value="@(((JObject)context.Variables["response"])["access_token"].ToString())" />
                    <set-variable name="duration" value="@(((JObject)context.Variables["response"])["expires_in"].ToString())" />
                    <cache-store-value key="token" value="@((string)context.Variables["token"])" duration="@(Int32.Parse((string)context.Variables["duration"]))" />
                </when>
            </choose>
            <!-- Use token for authorization
            <set-backend-service base-url="{{concur-url}}/api/v3.0/expense/reports?approvalStatusCode=A_APPR&amp;processingPaymentDateAfter=2024-09-10T04:59:33&amp;processingPaymentDateBefore=2024-10-01T10:57:37&amp;limit=100&amp;user=ALL" />
           -->
            <set-backend-service base-url="{{concur-url}}" />
            <set-header name="Authorization" exists-action="override">
                <value>@("Bearer " + context.Variables["token"])</value>
            </set-header>
            <set-header name="Content-Type" exists-action="override">
                <value>application/json</value>
            </set-header>
            <set-header name="Accept" exists-action="override">
                <value>application/json</value>
            </set-header>
            <set-variable name="calledOnce" value="@(true)" />
            <forward-request buffer-request-body="true" />
        </retry>
    </backend>

Tuesday, September 3, 2024

APIM Policy to send Data to servicebus managed identity

 <!--

    - Policies are applied in the order they appear.
    - Position <base/> inside a section to inherit policies from the outer scope.
    - Comments within policies are not preserved.
-->
<!-- Add policies as children to the <inbound>, <outbound>, <backend>, and <on-error> elements -->
<policies>
    <!-- Throttle, authorize, validate, cache, or transform the requests -->
    <inbound>
        <base />        
        <authentication-managed-identity resource="https://servicebus.azure.net/" output-token-variable-name="msi-access-token" ignore-error="false" />
        <set-backend-service base-url="https://myservicebus.servicebus.windows.net/" />        
        <rewrite-uri template="salesorder/messages" />
        <set-header name="Content-Type" exists-action="override">
            <value>vnd.microsoft.servicebus.yml</value>
        </set-header>
        <set-header name="Authorization" exists-action="override">
            <value>@("Bearer " + (string)context.Variables["msi-access-token"])</value>
        </set-header>
        <set-body>@{
                JObject json = context.Request.Body.As<JObject>(preserveContent: true);
                return JsonConvert.SerializeObject(json);
            }</set-body>
    </inbound>
    <!-- Control if and how the requests are forwarded to services  -->
    <backend>
        <base />
    </backend>
    <!-- Customize the responses -->
    <outbound>
        <base />
    </outbound>
    <!-- Handle exceptions and customize error responses  -->
    <on-error>
        <base />
    </on-error>
</policies>

Monday, May 14, 2018

Create New SharePoint Web coping sibling site content


Scenario

There are situations when you need to create duplicate the already created web using same site template, language and site structure. This article will cover how to use PowerShell to create new web, export sibling site and restore on new web. This process is dissected in three sections,
.

Create New Web

The basic PowerShell command to create web is following,


New-SPWeb -url "http://spsite/en-us/ACCOUNTING" -Name "Asset Accounting" 

If you want to use specific template for new web you can write following command,
New-SPWeb -url "http://spsite/en-us/ACCOUNTING" -Name "Asset Accounting" -Template BLANKINTERNET#2

You can find the installed templates from following command,
Get-SPWebTemplate

If you want to use specific template and specific language for new web, you can write following command,
New-SPWeb -url "http://spsite/en-us/ACCOUNTING" -Name "Asset Accounting" -Template BLANKINTERNET#2 -Language 1033
Note: 1033 is for English which is default. If we need to create this for arabic, use 1025.

Export Sibling Site

Following is command for exporting sibling site

Export-SPWeb "http://spsite/en-us/Finance" -Path "c:\firstbackup.bak" 

Import Backup to New Site

Now we have new site and backup of sibling site. We will now restore that backup to newly created web,

Import-SPWeb "http://spsite/en-us/ACCOUNTING" -Path "c:\financeaccount.bak" 

Monday, November 27, 2017

Why and How to implement Dependency Injection Pattern?

Benefits

By using dependency injection, you solve two main problems,

1- Unit Test
2- Instantiation

Unit Test

You can resolve this by implementing interface of every class that is required to instantiated in any method or implementation. Always pass interface as parameter in constructor rather than making variables and instantiate in the class. For unit test, you can send mocked (the dummy) instantiation of that interface to that class.

Before

        public class Order
        {
            public string ID { get; set; }
            public string Detail { get; set; }

            public void Process()
            {
            }
        }
        public class Cart
        {
            public void ProcessOrder()
            {
                Order order = new Order();
                order.Process();
            }
        }

Saturday, October 15, 2016

JavaScript Object References

Recently people asked me how JavaScript keep references while passing through function parameters including angular promise, underscore and normal JS code. I will provide one example from each section to show how references are passed.

Under Score (Lodash) Example

Some of the Underscore library functions return object reference while other returns new object. e.g. _.find method returns reference of the object that was found. in the following example when we change the value of variable "f.a", it affects "chkUnder" variable. While in case of _.where method, if we change the value of "w.a", it never changes the variable "chkUnder".

var chkUnder = [{ a: 1 }, { a: 2 }, { a: 3 }];
var f = _.find(chkUnder, { a: 2 });
f.a = 22;
var w = _.where(chkUnder, { a: 2 });
w.a = 24;

Wednesday, July 6, 2016

How to add Web API to an existing ASP.NET MVC Web Application

The steps I needed to perform were:
  1. Add reference to System.Web.Http.WebHost.
  2. Add App_Start\WebApiConfig.cs (see code snippet below).
  3. Import namespace System.Web.Http in Global.asax.cs.
  4. Call WebApiConfig.Register(GlobalConfiguration.Configuration) in MvcApplication.Application_Start() (in file Global.asax.cs), before registering the default Web Application route as that would otherwise take precedence.
  5. Add a controller deriving from System.Web.Http.ApiController.
I could then learn enough from the tutorial (Your First ASP.NET Web API) to define my API controller.
App_Start\WebApiConfig.cs:
using System.Web.Http;

class WebApiConfig
{
    public static void Register(HttpConfiguration configuration)
    {
        configuration.Routes.MapHttpRoute("API Default", "api/{controller}/{id}",
            new { id = RouteParameter.Optional });


// To return objects in Json format (Not XML Format),
var appXmlType = configuration.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
            configuration.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);

    }
}
Global.asax.cs:
using System.Web.Http;

...

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    WebApiConfig.Register(GlobalConfiguration.Configuration);
    RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

Use TypeScript in SharePoint Hosted App

There is trick involved in making Visual Studio realize to compile TypeScript and generate javascript files, Following procedure will give you complete guidance how to complete the process.

1.      Create a new Sharepoint-hosted app.
a.      Right-click the project name and select Unload Project.
b.      Right-click the project name and select Edit <your project name>.csproj.
c.      Add these lines before the last closing <Project> tag. 

    <TypeScriptSourceMap>true</TypeScriptSourceMap>
  </PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TypeScript\Microsoft.TypeScript.targets" />

1.      Right-click the project name and select Reload Project.
2.      Now you will see the TypeScript tab in the project properties.


2.      Now you can add the TypeScript definitions. Right-click the project name and select Manage Nuget Packages. Search online for “sharePoint.Typescript.” Install thesharePoint.Typescript.DefinitelyTyped package.      

3.      Also search for “jquery.typescript” and install the jquery.Typescript.DefinitelyTyped package.

Now you are ready to work with Typescript and can create Typescript files.