Blog

Angular Interceptor authorization: headers are now immutable

In Angular 4, headers are immutable, so to add (say) an Authorization header in your interceptor you have to use a cunning overload of the .clone method.

My complete interceptor looks like this…

import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from "@angular/common/http";
import { Observable } from "rxjs/Observable";
//import { FafService } from "./faf-service";
import { Injectable } from "@angular/core";
@Injectable()
export class FafInterceptor implements HttpInterceptor{
public theToken:string = null;
constructor(){
}
intercept(request: HttpRequest, next: HttpHandler): Observable<HttpEvent>
{
let theToken = window.localStorage.getItem('theToken');
//TODO: IsGuid
if(theToken && theToken != 'null'){
var NewRequest = request.clone(
{
setHeaders:{'Authorization': 'Bearer ' + theToken}
}
);
//https://angular.io/api/common/http/HttpRequest
console.log('auth header now ' + NewRequest.headers.get('Authorization'));
return next.handle(NewRequest);
}
return next.handle(request);
}
}

Angular mocking XHRBackend: how to call mockRespond

I’m adding unit tests to my API and had a bit of bother mocking the API response. However after a lot of console.log and much head scratching I found some voodoo that works.

TWO KEY TAKEAWAYS

1 . Josh Morony’s blog post said the call is

connection.mockRespond ( new Response ( newResponseOptions(...

That didn’t work for me, I had to use

connection.mockRespond ( newResponseOptions ( body: myObjects

2. But that’s not all, my live response (from a MS WebApi) has a ._body property, my mocked response has a .body. So I had to do something like this


if(res['body']){ //works with mocks
//...
}else if(res['_body']){//works in live system
//...
}

I started with this complete example:

git clone https://github.com/ionic-team/ionic-unit-testing-example.git

(The version numbers of the npm packages have to be compatible)

And worked through this blog post (and others!):

Test Driven Development in Ionic 2: Http and Mocks

This would have been a lot easier if I could figure out how to attach a debugger to Karma, no luck with that so far. Anyhow my complete dummy-service.spec.ts (including code for the service) is…

(just as soon as i figure out how to paste code into wordpress…)

import {Injectable} from '@angular/core';
import { Http, HttpModule, XHRBackend, ResponseOptions, Response } from '@angular/http';
import { TestBed, inject } from '@angular/core/testing';
import { MockBackend } from '@angular/http/testing';

@Injectable()
export class DummyService {
  access_token:string;
  constructor(public http:Http){}
  get(){
    console.log('DummyService Test1 F');
    this.http.get('http://localhost').subscribe((res:Response)=>{
      console.log('DummyService Test1 G got ' + JSON.stringify(res));
      if(res['body'] && res['body']['access_token']){
        this.access_token = res['body']['access_token']; //works with mocks
        console.log('loginUser got token from body (we are using a mock)');
      }else if(res['_body'] && JSON.parse(res['_body']) 
&& JSON.parse(res['_body']).access_token){
        this.access_token = JSON.parse(res['_body']).access_token; //works with live system
        console.log('loginUser got token from _body (we are live)');
      }
      console.log('access_token is ' + this.access_token);
    });
  }
}

describe ('DummyService http method',()=>{
  beforeEach(()=>{
    TestBed.configureTestingModule(
      {
        imports:[HttpModule],
        providers:[
          {provide: XHRBackend, useClass:MockBackend},
          DummyService
        ]
      }
    );
  }
  );

  it('should call get and get response',inject([DummyService, XHRBackend],(dummyService, mockBackend)=>{

    console.log('DummyService Test1 A');

    let r1 = "hello"; //works
    let r2 = "{access_token:'SOMETOKEN'}"; //works
    let r3 =  //doesn't work, service gets empty object {}
        new Response(
            new ResponseOptions(
            {
                url:'url',
                status:200,
                body: "here is the info"
            }
            )
        );
    let r4 = JSON.stringify(r3);//doesn't work, service gets empty object {}
    let r5 = new ResponseOptions( //aha THIS is the bunny...
        {
            body: {access_token:'SOMETOKEN'}
        }
        );

    mockBackend.connections.subscribe(
      connection=>{
        console.log('DummyService Test1 D v4 r5');
        connection.mockRespond(r5); 
      }
    );

    console.log('DummyService Test1 B');

    dummyService.get();

    console.log('DummyService Test1 C');
    
    expect(dummyService.access_token).toEqual('SOMETOKEN');

  }));

});

 

Upload changes only to your published web site (patch your web site files)

When you publish a web site you get all the files in a .zip or in a folder.

That’s a lot of files to transfer, especially if you can’t easily publish a package or you have a slow connection to your web server.

But with each version of the web site you have only changed a few files.

So after the first publish, write a .cmd or .bat file using xcopy to put just the changed files into another folder. Something like…

 

xcopy MyProject MyProjectUpdate /D:2-19-2018 /S /I /Y

 

/D:m-d-y Copies files changed on or after the specified date.
If no date is given, copies only those files whose
source time is newer than the destination time.
(change this every few days, and also clear out the destination folder MyProjectUpdate )

/S Copies directories and subdirectories except empty ones.

/I If destination does not exist and copying more than one file,
assumes that destination must be a directory.

/Y Suppresses prompting to confirm you want to overwrite an
existing destination file.

 

 

 

IonicCourseCode1

declare var $:any;




function onClickButton(){

        let url = 'http://transportapi.com/v3/uk/train/station/exc/live.json?'

            +'app_id=*****&'

            +'app_key=******************';
//get your own app_id and app_key from http://transportapi.com/v3/uk

        $.get(url).then(

            (data:any)=>{

                var x = data;

                let element = document.getElementById("statusText");

                if(element != null){

                    element.innerHTML = '<ul>';

    

                    for(var i=0;i<data.departures.all.length;++i){

                        let itm = data.departures.all[i];

                        let itmString = '<li>Plat ' + itm.platform

                            + ' Time ' + itm.expected_departure_time

                            + ' To ' + itm.destination_name + '</li>';

                        element.innerHTML += itmString;

                    }

                    element.innerHTML += '<ul>';

                }

                

            }

        );  

}

//(see c:\users\IonicNinja\Documents\TestTrainTimetable\index.ts)

sp_who you can filter

SELECT spid,
 sp.[status],
 loginame [Login],
 hostname, 
 blocked BlkBy,
 sd.name DBName, 
 cmd Command,
 cpu CPUTime,
 physical_io DiskIO,
 last_batch LastBatch,
 [program_name] ProgramName 
FROM master.dbo.sysprocesses sp 
JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
where hostname='BOARDROOM'
ORDER BY spid 


Get size of files using xp_cmdshell

Declare @Dir VARCHAR(256)
DECLARE @CMD VARCHAR(256)
SET @Dir = 'C:\myImageFolder\'
SET @CMD = 'DIR "'+@DIR+'" /A /S'

drop table #tmp 
 
 declare @media nvarchar(2048), @fn nvarchar(2048)
 DECLARE @CMD VARCHAR(256)

set @media = 'D:\Filestore\media'

SET @CMD = 'DIR "'+@media +'" /-C /S'

CREATE TABLE #tmp 
 (returnval NVARCHAR(500), rownum INT IDENTITY(1,1))

-- Populate Temp Table with the contents of the outfiles directory
 INSERT #tmp EXEC master..xp_cmdshell @cmd

alter table #tmp add filename nvarchar(255)
 alter table #tmp add size int
 alter table #tmp add DocumentId int

select convert(int,substring(returnval, 27,9)) size, substring(returnval, 37,999) name, * from #tmp
 where returnval like '__/__/____ __:__ %'
 --e.g. '17/11/2017 11:40 2645779 2017-11-17T114021.769Z001214 Band 4 Business Administrator Job Description_SM.pdf'

update #tmp set filename = substring(returnval, 37,999)
 , size = convert(int,substring(returnval, 27,9))
 where returnval like '__/__/____ __:__ %'

update #tmp set documentid=d.documentid from
 #tmp, documents d where d.documentpath like '%' + #tmp.filename


 select 
 filename, 'D:\MyStaffFile_Files\media\' + d.documentpath, s.assignmentid, size, d.documentid, createdby, createddate
 
 from #tmp inner join documents d on #tmp.documentid = d.documentid
 inner join sections s on d.sectionid=s.sectionid
 
 where size>1000000
 order by CreatedBy, CreatedDate, Size desc --documentid desc

 

What columns are used? Quick analysis of legacy SQL table

Got a table with lots of columns? Use this SQL to identify which have values.

My table name is manTransaction and I’m only interested in those of type = 2

declare @tn nvarchar(200)
declare @whereclause nvarchar(1024)
set @tn='manTransactionDetail' --table
set @whereclause = 'TransactionID in (select TransactionID from manTransaction where TransactionTypeID=8)' --particular records
declare @col nvarchar(200)
declare @typ int
declare @sql0 nvarchar(2048)
declare @sql nvarchar(2048)

set @sql0 = 'with a(v) as (select __COLNAME__ from __TABLENAME__ where __WHERECLAUSE__ )
 , d(v) as (select v from a group by v)
 insert into #ColumnStatus(ColName, DistinctValues) select ''__COLNAME__'', COUNT(*) from d'
set @sql0 = REPLACE(@sql0, '__TABLENAME__',@tn)
set @sql0 = REPLACE(@sql0, '__WHERECLAUSE__',@whereclause)

if OBJECT_ID('tempdb..#ColumnStatus') is not null drop table #ColumnStatus
create table #ColumnStatus(ColName nvarchar(200), DistinctValues int)
declare c cursor for
select name, system_type_id from sys.columns where object_id=object_id(@tn)
open c
fetch next from c into @col,@typ
set @sql = REPLACE (@sql0, '__COLNAME__', @col)
print @sql
exec(@sql) 
while @@FETCH_STATUS=0
begin
 fetch next from c into @col,@typ
 set @sql = REPLACE (@sql0, '__COLNAME__', @col)
 exec(@sql) 
end
close c
deallocate c
select ColName + ',' from #ColumnStatus where DistinctValues > 1

--select * from #ColumnStatus





 

 

MVC / Razor doesn’t post values from disabled html elements back to controller

In a Razor MVC form, if you disable a html element, the value won’t be posted back to the controller.

@Html.EditorFor(model => model.Person.Surname, new { htmlAttributes = new { @class = "form-control variable" } })

You might do

if (...) {
 $(".variable").attr('disabled', 'disabled'); //doesn't work
 }

Better, do this…

if (...) {
 $(".disable")
 .prop("readonly", true)
 .css('color', "#c0c0c0");
 //https://stackoverflow.com/a/2724483
 }

https://stackoverflow.com/a/2724483

Build Date for MVC or Visual Studio project

Shamelessly stolen from here

Project, create new folder Resources

Project, Properties: Build Events, Pre-Build event command line

echo %date% %time% > "$(ProjectDir)\Resources\BuildDate.txt"

Build your Project

Project, Resources: Create Default Resources File

..Add Resource, Existing File, …\Resources\BuildDate.txt

To read the build date, e.g. in a controller

protected override IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state)
 {

ViewBag.BuildDate = Properties.Resources.BuildDate;

...