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 !

Paypal exchange rate

I recently made some payments with paypal that requires the GBP currency.
I have added the GBP currency to my Paypal account.
I have a debit and a credit card in GBP currency (HSBC) that I use everyday.
I was not able to add these cards to Paypal. The process return the error “This card is not accepted. Please use a different card”.

I noticed that Paypal apply a particular disparaging exchange rate.
I usually use this site, xe.com that is more accurate of Google.
I concede they can use a little different exchabge rate, just enough to not loose money, but these differences seems exagerate to me.

Date Paypal XE.com Google Paypal diff
12 Jan 2017 0.81837 0.85198 8.85 + 3.94 %
10 Jan 2017 0.8196 0.85181 0.85 + 3.78 %

To calculate the percentage difference I used this formula:
Diff % = ((official_rate-paypal_rate) / official_rate) * 100

Once upon a time… software programmer

Job roles:
• Software developer (junior, medium, senior)
• Principal developer
• Lead Developer
• Team leader
• Tech leader
• Software engineer (junrior, medium, senior)
• Softwaree architect
• Business analyst (junrior, medium, senior)
• Full stack developer
• Front end developer
• Back end developer
• Developer manager
• Devops
• VP Engineer

Areas:
• FinTech – Financial & Capital Markets
• SciTech – R&D, Life Science & Medical Devices
• ConsulTech – Media, Telecoms, e-commerce
• DigitalTech – Business Consulting, Integrators & Vendors
• CriticalTech – Critical Infrastructure, Energy, Defence & Government

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

 

 

Set authentication on mongoDB

By default mongoDB access is public.
This is my note on setting up authentication, it is referred to mongoDB v 3.0.6 on Windows.

The command line parameter to start the service with authentication is:

--auth

(I’m sorry for all this space for writing two dash and a word but this shit of WordPress make it impossible in other ways)

From the same server you can connect to a database that is started with –auth but just for set up configuration (in older versions you could do more things).
You can create a user with the command db.createUser(…).
If you had just been connected you will receive an error which say you don’t have authorization.
You MUST change the current database to “admin” (use admin).
Now you can create a user, but just only one!

Remember:
1) If you create a user without a password you are fucked.
2) If you create a user in the admin database you are fucked.
3) If you create a user without admin roles you are fucked.

Create that user and give it the “userAdmin” (or userAdminAnyDatabase or dbOwner).
After you have correctly created the user you must reconnect with authentication to create more user and in general to manage roles.
In the current session you cannot do nothing else.
You cannot create, update, delete user neither see users (with show users command).

To connect with authentication use the -u, -p and -authenticationDatabase parameters.

Example:

mongo localhost:27123 -u <username> -p <password> -authenticationDatabase admin

Reference on mongoDB DOCS

 

FAQ

Q. Which permissison and roles are needed for execute show users command?
A.

Softonic

English language English

If you are looking for a (free) software and you finish to Softonic site… STAY AWAY FROM IT!

I found a good definition that I agree 100%:
“Softonic è un sito totalmente parassita. Installa software che con una banale ricerca in Google si può reperire da altre fonti. In più è una fonte di malware, troiani ed altre schifezze indesiderate. Dovrebbe essere pubblicamente smascherato. Si finanzia con pubblicità che installa poi in modo subdolo nei computer.”
(by andreina, here)

My translation:
Softonic site is a complete parasitic site. It install software that you just can find with a simple search on Google or that you can download from other sources. And it also is a source of malware trojan and other shit that you just not want. Shoud be publicly unmasked. Is financed by advertising that it install subtly on user’s conmputers.

Shoud be publicly unmasked.

You want a free software for doing some operation, try to ask me here, describing what you need. I will suggest you some if I know.


Lingua italiana Italiano

Se stai cercando un softare gratuito e sei finito sul sito Softonic… STANNE LONTANO!

Ho trovato una buona definizione, che condivido al 100%:
“Softonic è un sito totalmente parassita. Installa software che con una banale ricerca in Google si può reperire da altre fonti. In più è una fonte di malware, troiani ed altre schifezze indesiderate. Dovrebbe essere pubblicamente smascherato. Si finanzia con pubblicità che installa poi in modo subdolo nei computer.”

Dovrebbe essere pubblicamente smascherato.

Se ti occorre un softweare gratuito per una specifica operazione, prova a chiedermelo qui, descrivendo cosa ti serve. Se mi è possibile ti suggerirò qualcosa.

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)

Quanto costa vendere su eBay? Facciamo due conti su un caso reale

Ho acquistato su ebay un oggetto e lo ho pagato 141 euro compresa la spedizione di 11,00 euro.

Ho deciso quasi subito di rivenderlo.
Ho stabilito come prezzo di partenza 180,00 euro e ho aggiunto 10,00 euro per le spese di spedizione, per stare tranquillo di guadagnarci qualcosa.
L’asta è finita a 191 euro.
Bene! Ho guadagnato un sacco di soldi…

No. Giusto qualche spicciolo.
Il conteggio arrivato al compratore era 191,00 + 10,00 = 201,00 euro.
Mi ha pagato tramite PayPal (eBay spinge tantissimo per questo).
Sul conto Paypal sono entrati 201,00 euro a cui è stata applicata una commissione (“Fee amount”) di 7,18 euro.
Mi sono stati accreditati 193,82 euro.
Il costo epr creare l’annuncio su eBay era di pochi spiccioli, quasi gratuito; 0,30 euro per una fotografia aggiuntiva e 0,35 euro per la funzione “compralo subito”.
Ora che l’asta si è conclusa con una vendita mi viene addebitato anche un importo di 17,17 euro come “Commissione sul valore finale”.
Ho un debito risultante verso eBay di 18,63 euro.

Riepilogo:
141,00 –
193,82 +
18,63 –
——
34,19

Guadagno:
Alessandro: 34,19 euro
Poste: 22,00 euro
eBay: 18,63 euro
Paypal: 7,18 euro

Sono 82,00 euro esatti di costo aggiuntivo sul prodotto (!) che non hanno dato nessun valore aggiunto.
Chi l’ha venduto a me per 130,00 euro probabilmente lo ha pagato meno di 100 euro, l’utente a cui l’ho venduto io ha speso 201 euro.

40 minuti in posta per spedire il pacchetto e il lavoro per creare la vendita e seguirla (risposte agli utenti e rinnovo dell’asta per 4 volte ogni 10 giorni) non valgono i 34 euro guadagnati. Mai più.

… e speriamo che l’acquirente riceva il pacco e sia soddisfatto, perché ho spedito ieri mattina e chiaramente deve ancora arrivare!

Alcune note.
Quando ho acquistato l’oggetto (e anche ora che scrivo) lo stesso oggeto si trova in molte aste a un prezzo che oscilla dai 230,00 ai 285,00 euro; infatti pensavo di venderlo facilmente a oltre 200,00 euro. Invece sono stato per almeno un mese il venditore con il prezzo più basso su eBay per questo articolo, senza ricevere nessuna offerta, e l’asta era ben categorizzata a con una buona descrizione.
Credevo che spedire un pacchetto praticamente uguale come dimensione e come peso ad un pacco di pasta da 500g costasse meno. Invece c’era solo la scelta tra “Posta Raccomandata” a 11,euro o “Pacco celere 3” a 13,00 euro. Usare un corriere espresso è decisamente una alternativa da valutare.
L’oggetto è un Western Digital Black2, un disco SSD da 120GB e uno HDD da 1TB nello stesso supporto da 2,5 pollici (come un singolo HD per portatile), ma la scatola è voluminosa perché ci sono degli accessori ed è “scenica”.

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.