MVC API tests – manage unknown error raised by HttpServer

Scenario: integration tests against ASP.Net MVC API.
MVC version 5.2

Create a base class test to manage the repetitive API GET/POST calls like:

protected HttpResponseMessage Execute(HttpMethod method, string url, T data)
{
url = BASE_URL + url;

HttpRequestMessage request = new HttpRequestMessage(method, url);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

JsonMediaTypeFormatter formatter = new JsonMediaTypeFormatter();
formatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
if (method == HttpMethod.Post && data != null)
request.Content = new ObjectContent(data, formatter);

using (var server = new HttpServer(GetConfiguration()))
using (var client = new HttpClient(server))
{
var response = client.SendAsync(request).Result;
return response;
}
}

Boom.

500. Internal server Error.

The server is set like this:
private HttpConfiguration GetConfiguration()
{
HttpConfiguration configuration = new HttpConfiguration();
//var dependencyResolver = new WindsorDependencyResolver(container);
//configuration.DependencyResolver = dependencyResolver;
WebApiConfig.Register(configuration);

// remove all HostAuthenticationFilter due to the error “no OWIN Authentication manager…”
foreach (var filter in configuration.Filters.Where(f => f.Instance is HostAuthenticationFilter).ToList())
configuration.Filters.Remove(filter.Instance);

return configuration;
}

mmhh… try to debug:
It enter in the ApiController, get the data from the REpository and it exit from the class with a nice colelction of data… what is wrong ???

Routing is ok, it is actually passing the request to the right controller.
Injection of repositories is ok, it is fetching and returning data.
Log4Net is ok, I’m not calling the “log4net.Config.XmlConfigurator.Configure();” without a proper configuration in app.config.

Adding “configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;”
is absolutely useless for this problem.

What to do now?

I’ll check one of 2 or 3 previous project where I’ve already done this a where I spent 1,2 or 7 days to figure out this ALL THE TIMES fucking problem !

Microsoft ASP MVC 5

In MVC 5 Microsoft introduced the Attribute Routing functionality.
With it defining the Route for an Action become immediate and there is the advantage to be more safe when you change a routing, you cannot break previous routing rules.
To enable it you have to call the MapMvcAttributeRoutes() method on the RouteCollection.
GlobalConfiguration.Configuration.MapHttpAttributeRoutes();

Constraints on parameter type become more simple to define.
You can define optional parameters and default values more simply too.

Another feature I use all the time is the RoutePrefix: you can define the “controller” segment on the router only on the Controller definition, making more simple and readable changing the routes on the Actions.

You can continue to restrict the HTTP verbs allowed for an Action using [HttpGet], [HttpPost] and [AcceptVerbs]. This permits to have the same URL route for different Actions; for example you can request for the existence of a file (using HEAD) and to downlod the file (using GET) using the same URL.

[Route("Ping"), AcceptVerbs("Head", "Get")] 
public ActionResult Ping() {     return Content("pong (" + Request.HttpMethod + ")"); 
}

Sources:

  1.  https://blogs.msdn.microsoft.com/webdev/2013/10/17/attribute-routing-in-asp-net-mvc-5

 

 

ReSharper, what I don’t like of it

Versione 9.0 Update 1

No… these NOT:

  • use “var”
  • remove “using System;” (and System.Linq, System.Net, System.Net.Http…)
  • Intellisense: set on “Visual Studio”. With “ReSharper” selection I’ve not found immediately how to navigate overrides of method and it hide beautiful intellisense for AngularJS (and HTML%, CSS and HTML/Javascript in general from the fantastic “Web Essentials” free plugin)
  • JavaScript quote style. I have some with ‘ (single qutote) and some with ” (double quote), whart’s wrong?!
  • JavaScript: Function parameters not all in lowerCamelCase. Sorry, AngularJS style
  • Namespace does not correspond to file location. This is not Java, I want “MyProject.Test.IntegrationTest.MvcApplication.Api namespace for folder “Integration Test/MVC Appication/API”
  • Constant field (private) in “lowerCalmelCase”. No, I want the classic UPPER_CASE for constants
  • Possible multiple enumeration of IEnumerable. I’ve to live with that noise forever?
  • Constant field (not private) in “lowerCalmelCase”. No, I want the classic UPPER_CASE for constants
  • Field (not private) in “UpperCalmelCase”. No, I want the classic lowerCamelCase for this
  • Instance fields (private). Suggested name is “_xxx”. With underscore prefix? Why???
  • Use object initializer on EVERY new MyClass() in the code… ???
  • Field can be made readonly. Yes, yes, yes… but in test classes this is useless and code is more concise and readable without “readonly” everywhere.
  • JavaScript: Cannot resolve tag “…”. Of course! It is and AngularJS directive.
  • JavaScript: Replace with “strict” operator. No not everywhere!

WOW… this is very good

  • Class XXX inherited (click ti navigate)

NHibernate bag, list or set?

NHibernate semantics:

List

Ordered collection of entities, duplicate allowed. Use a .net IList in code. The index column will need to be mapped in NHibernate.

Set

Unordered collection of unique entities, duplicates not allowed. Use Iesi.Collection.ISet in code. It is important to override GetHashCode and Equals to indicate the business definition of duplicate. Can be sorted by defining a orderby or by defining a comparer resulting in a SortedSet result.

Bag

Unordered list of entities, duplicates allowed. Use a .net IList in code. The index column of the list is not mapped and not honored by NHibernate.

From here: http://stackoverflow.com/questions/1916350/list-vs-set-vs-bag-in-nhibernate

Primo approccio a mongoDB

Appunti sui problemi e soluzioni nati durante l’esperienza dell’utilizzo di mongoDB.

Windows 7 64 bit
mongoDB versione 2.4.4 (e successivamente 2.4.5)
Driver C# versione 1.8.1
Percorso dei file di mongoDB: C:\mongoDB
Cartella dei database: D:\Databases\mongoDB

2013-06-05

Errore su installazione con percorso personalizzato

Ho seguito alla lettera le istruzioni del tutorial sul sito ufficiale per creare il file di configurazione contenente il path del file di log.
Si presenta un errore riferito al file di configurazione che si è creato: [error per line ‘ |1’] o qualcosa di simile.

Ho risolto seguendo le indicazioni trovate su un articolo in internet, mi pare che abbia dovuto cancellare (l’ho rinominato) il file di configurazione prima di eseguire il comando --install e poi l’ho ricreato (rinominato con il nome originale).
Forse proprio questa operazione è stata la causa del problema riscontrato poi, ovvero il fallimento dell’avvio del servizio “MongoDB”.

2013-06-05

Errore su avvio del servizio “MongoDB”

L’installazione seguendo il tutorial sul sito ufficiale non è riuscita impostando un percorso personalizzato per i database.
Il problema che si presenta è il mancato avvio del servizio “MongoDB”, nel log viene segnalato che non viene trovato il percorso “/data/db” che è il percorso di default per i database.

Ho dovuto usare il comando da console trovato su un articolo in internet per ovviare al problema.
Di fatto il tutorial pur indicando che si può personalizzare il percorso dove verranno salvati i database non dà indicazioni corrette sull’installazione. Nelle FAQ non ho trovato nulla al riguardo.

2013-06-06

Errore “Element ‘_id’ does not match any field or property of class PersonalFinance.Entities.User.

L’errore è dovuto alla mancanza di una proprietà “Id”.


using MongoDB.Bson;
public ObjectId Id { get; set; }

Le mie classi entità si trovano in un apposito progetto, con namespace “Entities”.
Purtroppo essendo usate anche nel progetto di interfaccia (Web site) devo aggiungere la referenza alla libreria a MongoDB.Bson.dll anche in quest’ultimo, e di questo non sono contento.

La proprietà “Id” è anche usata nel metodo Save().

2013-08-05

Nuova installazione su un altro PC

Download del file mongodb-win32-x86_64-2.4.5.zip ed estrazione della cartella bin in S:\mongoDB.

Inizio l’installazione e quindi eseguo il comando:
mongod.exe--dbpath "d:\Databases\mongoDB"

Tutto sembra andare a buon fine in quanto mi trovo con alcuni file creati nella cartella che conterrà i database ed il prompt che mi informa che il server è in ascolto sulla porta 27017, il “waiting for connections message” menzionato dalla guida.
Con un’altra console dos riesco a interagire con il server.

Passiamo all’installazione del servizio.
Come la guida richiede creo la cartella per i log, S:\mongoDB\log.
Poi creo il file s:\mongoDB\bin\mongod.cfg e ci scrivo:
logpath=S:\mongoDB\log\mongo.log
senza andare a capo a fine linea.

Poi però aggiungo l’opzione per indicare il percorso dei database, quindi su una nuova linea:
dbpath=D:\Databases\mongoDB
e non vado a capo a fine linea.

Ora eseguo il comando per installare il servizio:
mongod.exe --config S:\mongoDB\bin\mongod.cfg --install

Ok, dopo il primo errore “Access is denied (5)” riprovo facendo partire la console DOS con “Run as administrator”.
Servizio installato.
Con il comando net start mongoDB dovrebbe partire…

E invece:

The Mongo DB service could not be started.
A system error has occurred.
System error 1067 has occurred.
The process terminated unexpectedly.

Mi stavo già per arrabbiare, ma poi vedo che in Notepad++ il file mongod.cfg non è salvato.
Lanciando il comando mongo nell’output si legge che sta cercando di accedere alle cartelle /data/db che non vengono trovate.
Uso mongod --remove per rimuovere il servizio e dopo aver salvato il file mongod.cfg ripeto installazione e starto il servizio. Questa volta funziona tutto.

2013-10-26

Unique key

Dovendo associare all’utente loggato nella mia applicazione una valuta ho pensato di creare un’entità “Currency” contenente il nome ed il simbolo della valuta. Non volendo creare Model, View e Controller per inserire 2 valute (euro e dollaro) ho optato per l’altra via: usare la shell. In realtà ho usato un file script (.js) che richiamo con un semplice doppio click. Devo dire che però inserire e semplici recor in una tabella di 3 campi (“Code”, “Name” e “Symbol”) e poi la chiave indice univoco sul campo “Code”, non è stato immediato. Poi ho dovuto collegare ai document “Account” (la mia collection per gli utenti) le “Curency”. Anche qui tramite script.
I simboli (inseriti con il file script) non vengono mostrati, forse dovrei usare la stringa ”\u20ac” per l’euro.
Volevo creare in prima battuta degli oggetti falsi, invece comunque ho dovuto creare l’entità “Currency” e la classe CurrencyRepository che mi legge dal database la Currency. Con un database relazionale avrei creato sul database come indice univoco e chiave primaria il solo campo “Code” e quindi sarebbe stato immediato creare gli oggetti in memoria.

2013-10-26

Oggetti relazionati

Ho ora un problema con gli oggetti relazionati.
Nella documentazione ufficiale si consiglia di usare l’embed per tenere le relazioni tra gli oggetti, in quanto altrimenti necessitano più query per ottenere il dato.
In questo modo però l’aggiornamento dell’oggetto relazionato (di alcune sue proprietà) non si ripercuote in tutti gli oggetti dove è stato inserito. Se invece nell’oggetto iniziale si inserisce solo un campo che serva per relazionare le entità, nel caso di liste dell’oggetto di partenza come si ottengonop gli oggetti relazionati (quello che in SQL sarebbe un inner join)? E nel caso di ulteriori sotto-relazioni?
Se non trovo una soluzione semplice a questo, dovrò passare tutto il progetto che ho basato su mongoDB ad un database relazionale (SQL Server + NHibernate, sono la scelta più probabile).

Alla fine sono passato a SQL Server perché le mie entità sono tutte relazionate e lavorare con Mongo su entità relazionate è un delirio.