Ta-da! Oh, wait…

I’m not going to make any excuses – I’ve just failed. The current state is that I can display advertisements within a category, display some of their details and register a new user. It doesn’t even look decently – I’m not good at designing UI in general nor is Bootstrap sufficient alone, so the visual part will require some unpleasant effort.

What I’ve done well is learning TypeScript (to some extent) and Angular 2 (to some larger extent) from scratch and I rather like both of them. Ah, and another achievement is holding on until the end of the contest.

What I could have done better is getting started faster (abandoning ambitions to do it perfectly at once), registering earlier, designing earlier. There was time pressure because of late registration and no possibility of having a break, which resulted in writing code and blog posts in a hurry and I think it’s easy to notice. I could have also got familiar with Bootstrap at the very beginning, provided a mock layout (even only on a branch or a few ones) and implemented behavior afterwards. I’ve done it the other way around, so screenshots presented here were ridiculous and sparse. I was ashamed of showing them, so I limited posts to text only which looks uninteresting.

What I’ve done completely wrong is choosing an incorrect database system. I chose technologies because I wanted to deal with them, the application itself was only a supplement. It turned out to be impossible to model my data using a hierarchical structure which is essential in MongoDB. Using it the same way as a relational database is absolutely insecure and may lead to data inconsistency. There should be some thread safe solution for accessing the database, but I was already fed up with the topic and I decided to continue anyway.

What I’m going to do next is continuation of implementing at least some of the planned functionality, but rather without writing here regularly, in order not to pollute the Internet anymore.

Registering a user

I’ve been working on logic related to users recently – I need registration, logging in and authorization to actions. This is all available out of the box in default project templates in ASP.NET MVC/Web API which are shipped together with Entity Framework and SQL Server, but I have none of them here. ūüôā I’ve only implemented registration by now, which was simple on the server side (just adding a document with little validation), but more challenging on the client side. I took care of interaction – when I do something, then something (dis)appears or a message is (un)set. So I took an opportunity to learn how to pass data between components.

First option is from the outside into a component. This is simple – add a decorator to the component’s field:

@Component({
	moduleId: module.id,
	selector: 'feedback-message',
	templateUrl: 'component.html'
})
export class FeedbackMessageComponent {
	@Input()
	text: string;
}

And then assign a value to it in a parent component’s template:

<feedback-message [text]="feedback"></feedback-message>

One thing to remember here: square brackets – they mean the direction is from the outside into the component and indicate binding to the value of a parent’s class field, not to the string “feedback”. If these brackets are missing, then the literal string is passed to the component.

Second option is passing data outside of a component, which is done using an @Output decorator:

export class RegisterUserComponent {
	@Output()
	submitForm = new EventEmitter<RegistrationResult>();
	...
}

When something happens in a component and we want to announce it, an event must be raised:

registerUser() {
	this.registerUserService.register(this.user)
		.then(() => {
			const result = new RegistrationResult(RegistrationStatuses.ok, TextConstants.registrationSuccessful);
			this.submitForm.emit(result);
		}).catch(() => {
			const result = new RegistrationResult(RegistrationStatuses.failed, TextConstants.errorOccurred);
			this.submitForm.emit(result);
		});
}

Sending data is optional. If there is nothing necessary, the type parameter of EventEmitter can be void.

And from the parent’s perspective:

<register-user *ngIf="isRegisteringUser" (submitForm)="registrationSubmitted($event)"></register-user>
registrationSubmitted(result: RegistrationResult) {
	this.feedback = result.message;
	this.isRegisteringUser = (result.status === RegistrationStatuses.failed);
}

The data are accessed thanks to $event passed in HTML. And notice the attribute – it is in round brackets, which means that direction of data flow is from a component to the outside.

Both @Input and @Output accept a string parameter which specifies a name of the attribute whose value will be assigned to the decorated field. If that parameter is missing, then the attribute must have the same name as the field.

Fixing structure of the client-side code

Since code keeps growing, it turns out that the client side’s structure is far from perfect. I used to have a root containing 2 folders with components and services respectively, and some other common or general stuff. That can be enough for a tutorial, but I’m slightly more ambitious and organized. Also, declarations of every single service polluted the root module in order to make it available in lower levels in hierarchy. Even the documentation recommends organizing services in a hierarchy according to the component tree in order to limit access to them to relevant components only. Import paths are much simpler then as well. So that’s what I’ve done recently – added a bunch of folders for separate pieces of behavior, moved everything suitable into them and adjusted references. Sounds like a piece of cake, but it took some time – the VS Code’s Problems panel doesn’t list all the existing errors from everywhere, but only from open files, I guess. So I had to update a lot of paths in imports after runtime errors. Now services are declared at the lowest possible level – in components, like below (names are sample, the tree in my code is higher):

Refactor
This is different than in C# where I have one project with all the controllers and another one with all the services. But in C# it works much easier – imports don’t refer to single files only and in particular they don’t refer to file locations.

There could be probably something more done to split the main module into smaller ones so that not only services, but also components are registered on appropriate lower levels only. I’ll consider it in the future though, maybe after having some tests, because now it’s not so burdensome.

Finishing details of an advertisement

There is not much to write about this time. I’ve added a few issues on GitHub so that I have something to do in the following year. Concerning code, the progress is that I’ve added displaying details of an advertisement, which required some refactoring due to existing logic for getting general data for a list of advertisements. It is recommended not to load the whole database entities when we need only a part of the data, so I’ve separated view models on both the API and the client side. Adding new code was rather typical and tedious – a controller action, a service method, a repository method, pulling it all from a client service… I’m not going to show the view because it still needs some styling (or, to be honest, any styling). I want to have some working functionality first in order to measure what I’ve done and it will also give me content to style consistently using Bootstrap.¬† There is no fun in introducing a giant set of CSS only for a few divs, right?

A cleaner way to prepare requests

Oops, I’ve messed up something in the repository and changes described in the previous post disappeared… Fortunately there wasn’t that much to restore and code cited in the previous post helped, so I’ll add something else. I wanted to define a request timeout to catch situations when a database is down. The default timeout is probably 30 seconds long and it’s too much for me to wait. I didn’t want to bother about setting timeouts everywhere so I’ve extracted a method for executing requests to the API. There are 2 common parts of executing a request: converting it to a promise and defining its “catch” block. So the common method gets content of a “then” block as a parameter and performs those two things:

import { Injectable } from "@angular/core";
import { Response as HttpResponse } from '@angular/http';

import 'rxjs/add/operator/toPromise';
import 'rxjs/add/operator/timeout';
import { Observable } from "rxjs/Observable";
import { TimeoutError } from "rxjs/util/TimeoutError";

import { LogService } from "./log.service";

@Injectable()
export class RequestHelper {
    constructor(private logService: LogService) { }

    getPromiseFromRequest<TResult>(request: Observable<HttpResponse>, thenCallback: (response: HttpResponse) => TResult): Promise<TResult> {
        return request.timeout(3000).toPromise()
            .then(response =>
                thenCallback(response)
            ).catch(reason => {
                if (reason instanceof TimeoutError) {
                    this.logService.log(reason.stack);
                    throw new Error();
                }
                else {
                    this.logService.log(reason.json());
                }
            });
    }
}

The purpose of throwing a new error is only to activate a “catch” block in a consumer of a service – in order to display a message. There is no need to have the original stack trace.

There was a little confusing error:

Types of parameters ‘response’ and ‘response’ are incompatible. Type ‘Response’ is not assignable to type ‘Response’. Two different types with this name exist, but they are unrelated.

because there are 2 predefined types called Response – one is a class in the @angular/http module, the other is an interface in typescript. That’s why I had to import it with an alias:

import { Response as HttpResponse } from '@angular/http';

Could be better if the error message already contained a hint from where I can import…

And a usage is:


...
export class CategoryService {
    constructor(private http: Http, private requestHelper: RequestHelper) { }

    private getCategoriesCallback(response: HttpResponse) {
        let categories: any[] = response.json();
        let result: Category[] = categories.map(category => new Category(category.Id, category.Name));
        return result;
    }

    getCategories(): Promise<Category[]> {
        let url = Constants.urlBase + `categories`;
        return this.requestHelper.getPromiseFromRequest(this.http.get(url), this.getCategoriesCallback);
    }
};

Loading basic data from a database – done

Following the pattern from yesterday, I modified the service which gets a list of categories to get them from a database instead of a mock. As a side effect of both operations Jasmine tests are gone, because now I need to adjust them to depend on some mock Http. I’m not sure when it will be possible though – deadlines are coming… Yes, it’s the most common and the most incorrect excuse from not writing tests, but in this case I can still afford them after the end of May. No doubt I won’t finish on time, so I’ll continue afterwards to achieve something publishable.

A service communicating with a database can return errors, so I also added handling them – meaning logging the whole available stuff and displaying a gentle message for a user. For the purpose of messages and some UI elements coming soon, I’ve added a temporary constant object which acts as a source of texts, so that they are not hardcoded. I won’t provide support for foreign languages (because nobody creates several versions of an advertisement), but keeping constant strings in one place is a good practice.

In order to present a message when there is an error, I’ve designed services to return a promise with an optimistic path only. To say it simpler: an asynchronous action (a request to the API) is executed. A promise provides an interface which lets us handle two situations: when a promise is resolved (which is an arbitrary term for an optimistic path – in my case it’s when the request returns data correctly) or rejected (the pessimistic path – when an exception has been thrown or the promise has been rejected explicitly). I’ll add the rejection stuff only in components. An example for loading categories:

CategoryService:

...
@Injectable()
export class CategoryService {
    constructor(private http: Http) { }

    getCategories(): Promise<Category[]> {
        let url = Constants.urlBase + `categories`;
        return this.http.get(url).toPromise()
            .then(response => {
                let categories: any[] = response.json();
                let result: Category[] = categories.map(category => new Category(category.Id, category.Name));
                return Promise.resolve(result);
            });
    }
};

app.component, the current main one:

export class AppComponent implements OnInit {
    header = 'Addregator';
    categories: Category[];
    errorMessage: string;

    constructor(private categoriesService: CategoryService, private logService: LogService) { }

    ngOnInit(): void {
        this.categoriesService.getCategories()
            .then(categories =>
                this.categories = categories
            ).catch(reason => {
                this.logService.log(reason.json());
                this.errorMessage = TextConstants.errorOccurred;
            });
    }
}

and its poor template:

<h1>{{header}}</h1>
<ul>
	<li *ngFor="let category of categories">
<a routerLink="categories/{{category.id}}" routerLinkActive="active">{{category.name}}</a></li>
</ul>
{{errorMessage}}
<router-outlet></router-outlet>

(WordPress sucks a bit in formatting…)
then() and catch() mean resolve and reject handling respectively. As we can see, then() is doubled – the first one is in the service, the second in the component. This is chaining in practice – if everything goes well, the former then’s returned value is an input to the latter one. Otherwise only catch() from the component is called:

Error handling

Restricting access to a server using CORS

Since I’ve already created an endpoint in my API and an Angular service working with a mock, it’s not rocket science to bind them together, is it? Actually, there’s a little trick… When I tested the endpoint using Postman, everything was fine – breakpoints in the API were hit, a response was sent and displayed correctly. But when I modified the service to talk to the API, breakpoints were hit, a response was sent, but on the client side I couldn’t get its actual content, no matter whether the request was valid. I tried a few solutions with Promises (in simple words: a JavaScript wrapper for asynchronous actions which can return some particular result data or an error and be easily chained) and Observables (something similar to promises and the Observer pattern). In all cases the error path was executed and the response contained a weird object:

{
    "_body": {
        "isTrusted": true
    },
    "status": 0,
    "ok": false,
    "statusText": "",
    "headers": {},
    "type": 3,
    "url": null
}

I was logging responses to the console, so I missed an important message appearing there as well for a long time…

XMLHttpRequest cannot load http://localhost:27365/api/categories/5904c5fa2e529525cfcc81a9/advertisements. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:3000 ‘ is therefore not allowed access.

What the heck if Postman could do it? The answer is CORS – Cross-Origin Resource Sharing, a security mechanism which defines what requests are allowed to access resources. As you can see in the message, a client and a server are hosted on different ports, so technically speaking they have different origin. This is why requests were actually blocked on the server side, even though breakpoints were hit there and the correct data were returned… The solution was to turn on CORS on the server side. There is an easy introduction¬†here¬†which explains the topic and describes what I’ve done. To cut a long story short, it only requires installing a Nuget package called Microsoft.AspNet.WebApi.Cors and adding the following in WebApiConfig.Register(), in the same place where routing is set:

var cors = new EnableCorsAttribute("http://localhost:3000", "*", "*");
config.EnableCors(cors);

This is my case where I allow any requests from that particular URL. Alternatively we can limit them to some headers or methods (the other parameters above), controllers or actions (then place an EnableCors attribute on them instead).
And here is a little explanation why Postman could pass. I’m not sure if it’s fully relevant because I use a desktop version, but I guess it works in a similar way.

By the way, by fixing this problem I’ve finally closed another GitHub issue. ūüôā