Tworzenie paczek NuGet

W skrócie opisze jak tworzyć paczki nuget bezpośrednio z projektu VS.

Wszystkie polecenia będziemy wykonywać narzędziem nuget.exe

Tworzenie paczki release

W folderze z projektem (plik .csporj) uruchamiamy

nuget spec

Po uruchomieniu zostanie utworzony specjalny plik .nuspec o takiej samej nazwie jak nazwa projektu. Plik ten zawiera meta informację na temat paczki.

[xml]
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<releaseNotes>My project release notes</releaseNotes>
<copyright>Copyright 2016</copyright>
<tags>tag1 tag2</tags>
</metadata>
</package>
[/xml]

Dane w formacie $xyz$ oznaczają że te informacje są pobierane z pliku dll.

Gdy plik nuspec mamy już gotowy to budujemy projekt i tworzymy paczkę uruchamiając polecenie:

nuget pack MyProject.csproj

Jeśli chcemy dodać zależne biblioteki to dodajemy parametr IncludeReferencedProjects

nuget pack MyProject.csproj -IncludeReferencedProjects -Prop Configuration=Release

Jeśli paczka się utworzy to wysyłamy ją na serwer poleceniem:

nuget push MyProject.1.0.0.nupkg -s http://yourdomain.com/nuget API_KEY

Tworzenie paczki prerelease

Jeśłi paczkę tworzymy z pliku projektu (.csproj lub .vbproj) to utworzenie paczki prelese ogranicza się do dodania atrybutu AssemblyInformationalVersionAttribute i określeniu wersji:

[assembly: AssemblyInformationalVersion("1.0.1-alpha")]

NuGet użyje tej wartości zamiast danych z AssemblyVersion.

Więcej informacji

Własny serwer NuGet

Każdy kto korzysta z VS wie co to NuGet i jak bardzo on upraszcza życie, dodawanie zewnętrznych bibliotek jest banalnie proste, aktualizacja do nowej wersji – jedno kliknięcie i gotowe. A co jeśli taki serwer możemy sobie sami postawić. O ile prostsze było by współdzielenie bibliotek we własnych projektach. Może w firmie której pracujecie dalej ręcznie podpinacie biblioteki, warto zaproponować postawienie takiego serwera – trwa to chwilę, a uprasza bardzo wiele.

Tworzenie własnego serwera

  1. Tworzymy pusty projekt ASP.NET Web Application (ASP.NET 4.x)
  2. Instalujemy paczkę NuGet.Server
  3. Wdrażamy aplikację na docelowy serwer
    NuGet jest dostępy pod adresem http://yourdomain/nuget
  4. Konfigurujemy i cieszymy się własnym serwerem NuGet

Konfiguracja

Konfiguracja to ustawienie odpowiednich wpisów w pliku web.config

Pierwsze co robimy to ustawienie klucza umożliwiającego wrzucanie paczek:

[xml]
<add key="apiKey" value="YOUR-API-KEY" />
[/xml]

Na czas testów możemy ustawić allowOverrideExistingPackageOnPush na true, co może się przydać jak zaczniemy uczyć się tworzyć paszki i wrzucać je na serwer.

[xml] <add key="allowOverrideExistingPackageOnPush" value="false" /> [/xml]

Wrzucanie paczek

Paczki wrzucamy aplikacją nuget.exe z parametrem push:

[bash]
nuget push {packagefile} -s http://yourdomain/nuget {apikey}
[/bash]

Kunfiguracja VisualStudio

Aby paczki z naszego serwera były widoczne w VS musimy dodać go do listy Package Sources. Aby to zrobić w VS 2015 otwieramy okno dodawania źródeł dla nugeta: Tools -> NuGet Package Manager -> Package Manager Settings.

W otwartym oknie wybieramy Package SourcesNuGet Package Sources

Klikamy dodaj i uzupełniamy dane naszego serwera.

Po zatwierdzeniu nasz serwer jest już widoczny na liście:NuGet Package Sources List

Teraz już możemy instalować z niego paczki.

Podsumowanie

Jak widać instalacja i konfiguracja własnego serwera NuGet to tylko kilka minut, a korzyść bardzo wiele. Myślę że warto to wdrożyć dla swoich projektów jak również w firmie jeśli dalej ręcznie podpinacie zewnętrzne biblioteki.

Więcej informacji:

The Clean Architecture

Prezentacja wujka Boba na temat Clean Architecture

Główne założenia Clean Architecture

  • Struktura projektu powinien odzwierciedlać architekturę, a nie użyty framework (Screaming Architecture).
  • Elementy takie jak UI, serwer, baza danych, użyty ORM to szczegóły który powinny być ukryte
  • Testowalność – reguły binzesowe można testować nieleżenie od UI, użytego serwera, bazy danych itd.
  • Wykorzystanie Dependency Inversion principle

Więcej informacji:

Effective software delivery

Opis z YouTube: Podczas tej prezentacji przejdziemy przez poszczególne fazy dostarczania oprogramowania i odpowiemy sobie na pytanie jakie możliwości optymalizacji mamy do dyspozycji na poszczególnych etapach. Powiemy sobie jakich błędów unikać poczas prototypowania, jak wykorzystać specyfikę projektu i nie dać się ponieść pragnieniu rozwiązywania wszystkich problemów za pomocą złotego młotka. Poruszymy mit spowalniających development testów automatycznych, odpowiemy na pytanie czy DRY mówi tylko o unikaniu copy-paste w naszej aplikacji oraz przeanalizujemy szerzej zagadnienie przedwczesnej optymalizacji. Poznamy także narzędzia i techniki, która pozwalają nam efektywniej pracować nad wytwarzaniem oprogramowania.

Zasady dobrego programisty

Don’t Repeat Yourself (DRY) – nie powtarzaj się

Jest to jedna z najważniejszych zasad i powinniśmy traktować ją bardzo poważnie. Objawia się ona nie tylko powielaniem tego samego kodu i używanie metody Copy&Paste.

Single-Responsibility Principle (SRP) – zasada pojedynczej odpowiedzialności

Żadna klasa nie może być modyfikowana z więcej niż jednego powodu.

Jeśli jesteśmy w stanie wyobrazi sobie więcej niż jeden bodziec skłaniający programistę do zmiany klasy, mamy do czynienia z klasą rozciągającą się na więcej niż jeden obszar odpowiedzialności.*

Open/Close Principle (OCP) – zasada otwarte-zamknięte

Składniki oprogramowania (klasy, moduły, funkcje itp.) powinny być otwarte na rozbudowę, ale zamknięte dla modyfikacji.

Na początku może wydawać się to sprzeczne bo jak mamy wprowadzać zmiany skoro nie możemy modyfikować kodu. Odpowiedzią jest abstrakcja. W świecie obiektowym abstrakcje mają postać abstrakcyjnych klas bazowych, a grupa niezwiązanych, możliwych zastosowań jest reprezentowana przez klasy pochodne.
Moduł, który wykorzystuje abstrakcje, może być zamknięty dla modyfikacji, ponieważ jego działanie jest uzależnione właśnie od tej abstrakcji. Dzięki temu mamy możliwość rozszerzania tego modułu bez potrzeby modyfikacji jego kodu.

Liskov Substitution Principle (LSP) – zasada podstawień Liskov

Musi istnieć możliwość zastępowania typów bazowych ich podtypami.

Znaczenie tej zasady staje się oczywiste, kiedy rozważymy konsekwencje jej naruszenia. Przypuśćmy, że dysponujemy funkcją f, która otrzymuje za pośrednictwem swojego parametru referencję do pewnej klasy bazowej B. Załóżmy także, że przekazanie na wejściu funkcji referencji do klasy D (potomnej względem klasy B) powoduje błędne działanie tej funkcji. W takim przypadku klasa D narusza zasadę podstawienia Liskov (LSP). Oznacza to, że klasa D jest wrażliwa w kontekście funkcji f.
Prostym przykładem naruszenia tej zasady jest weryfikacja typów za pomocą instrukcji if-else

Dependecy-Inversion Principle (DIP) – zasada odwracania zależności

Moduły wysokopoziomowe nie powinny zależeć od modułów niskopoziomowych. Obie grupy modułów powinny zależeć od abstrakcji.

Abstrakcje nie powinny zależeć od szczegółowych rozwiązań. To szczegółowe rozwiązania powinny zależeć od abstrakcji.

Interface Segregation Principle (ISP) – zasada segregacji interfejsów

Ma na celu wyeliminowanie nieporęcznych “grubych” interfejsów. Do tej grupy zaliczamy nadmiernie rozbudowane i niespójne interfejsy klas. Innymi słowy, interfejsy takich klas należy dzielić na mniejsze grupy metod. Każda taka grupa odpowiada za obsługę innego zbioru klientów. Oznacza to, że część klientów będzie korzystała z jednej grypy metod, podczas gdy pozostałe aplikacje klienckie będą korzystały z pozostałych grup metod.

Zasada skautów: Pozostaw obóz czyściejszym, niż go zastałeś.

(Staraj się pozostawić ten świat nieco lepszym niż go zastałeś)

*Stosowanie reguł jest błędem, jeśli nie znajdujemy uzasadnienia w sytuacji faktycznej. O osi zmian możemy mówić wtedy i tylko wtedy, gdy odpowiednie zmiany mają miejsce.

Bibliografia:

  • Agile Programowanie zminne, Robert C. Martin, Micah Martin
  • Czysty kod, Robert C. Martin

The transaction log for db BizTalkMsgBoxDb is full.

SQL Server returned error string: “The transaction log for database ‘BizTalkMsgBoxDb’ is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases”.

Solution:

[sql]

sp_helpdb ‘BizTalkMsgBoxDb’

ALTER DATABASE BiztalkMsgBoxDb

SET RECOVERY SIMPLE;

GO

DBCC SHRINKFILE (BiztalkMsgBoxDb_log, 1);

GO

sp_helpdb ‘BizTalkMsgBoxDb’

GO

ALTER DATABASE BiztalkMsgBoxDb

SET RECOVERY FULL

GO

[/sql]

MSCRM 4.0 Web Service Toolkit (JavaScript)

 CRM Web Service Toolkit jest małą JavaScript’ową biblioteką umożliwiającą łatwy dostęp do web serwisów Microsoft Dynamics CRM 4.0.
Dzięki niej możemy w szybki sposób:

  • tworzć/aktualizować encje
  • zmieniać stan encji
  • tworzyć zapytania za pomocą fetchXML czy poprzez metodę RetrieveMultiple
  • i wiele innych metod dostępnych w web serwisach CRMa

Przykłady

Encje tworzymy za pomocą metody CrmServiceToolkit.Create()

[js]

// Use CrmServiceToolkit. Create() to create a CRM contact record.
var contact = new CrmServiceToolkit.BusinessEntity("contact");
contact.attributes["firstname"] = "Diane";
contact.attributes["lastname"] = "Morgan";
contact.attributes["gendercode"] = 2;
contact.attributes["familystatuscode"] = 1; // Picklist : Single – 1
contact.attributes["creditlimit"] = 3000;

var createResponse = CrmServiceToolkit.Create(contact);

[/js]

CrmServiceToolkit.Retrieve() używamy do zwracania pojedynczych encji

[js]
// Use CrmServiceToolkit.Retrieve() to retrieve a CRM contact record.
var contactId = ‘3210F2BC-1630-EB11-8AB1-0003AAA0123C’;
var cols = ["firstname", "lastname", "familystatuscode", "creditlimit", "birthdate", "donotemail"];
var retrievedContact = CrmServiceToolkit.Retrieve("contact", contactId, cols);

alert(retrievedContact.getValue(‘lastname’));
alert(retrievedContact.getValue(‘firstname’));
// Picklist value (integer)
alert(retrievedContact.getValue(‘familystatuscode’));
// Picklist selected text
alert(retrievedContact.getValue(‘familystatuscode’, ‘name’));
// Currency field value
alert(retrievedContact.getValue(‘creditlimit’));
// Currency field formatted value (string)
alert(retrievedContact.getValue(‘creditlimit’, ‘formattedvalue’));
// Datetime field date/time value
alert(retrievedContact.getValue(‘birthdate’));
// Datetime field date string
alert(retrievedContact.getValue(‘birthdate’, ‘date’));
// Datetime field time string
alert(retrievedContact.getValue(‘birthdate’, ‘time’));
// Bit field value
alert(retrievedContact.getValueAsBoolean(‘donotemail’));
[/js]

Metoda CrmServiceToolkit.setState() umożliwia nam zmiane stany encji

[js]
// Use CrmServiceToolkit.setState() to update a CRM record status.
var contactId = ‘3210F2BC-1630-EB11-8AB1-0003AAA0123C’;
var response = CrmServiceToolkit.setState(‘contact’, contactId, ‘Inactive’, 2);
alert(response);
[/js]

CrmServiceToolkit.queryByAttribute() zwraca nam wszystkie rekordy spełniające podane kryterja.

[js]
// Use CrmServiceToolkit.queryByAttribute() to retrieve all CRM records that match the query criteria.
var queryOptions = {
entityName : "contact",
attributes : ["firstname", "lastname"], // Search by firstname and lastname
values : ["John", "Smith"], // Find all contacts whose firstname is John, lastname is Smith
columnSet : ["familystatuscode", "creditlimit", "birthdate"],
orderby : ["creditlimit", "birthdate"]
};

var fetchedContacts = CrmServiceToolkit.queryByAttribute(queryOptions);
[/js]

Więcej informacji na:

http://crmtoolkit.codeplex.com/

http://danielcai.blogspot.com/2010/07/crm-web-service-toolkit-for-javascript.html

MSCRM 4.0 Form Properties

Do pól formularza odwołujemy się poprzez obiekt crmForm:

[js]
crmForm.propertyname
[/js]

Tabelka poniżej przedstawia dostępne właściwości.

Właściwość Typ Opis
IsDirty bool Określa czy formularz był modyfikowany
FormType int Tylko do odczytu. Typ formularza.Możliwe wartości:

  • Undefined Form Type = 0
  • Create Form = 1
  • Update Form = 2
  • Read Only Form = 3
  • Disabled Form = 4
  • Quick Create Form = 5
  • Bulk Edit Form = 6
ObjectId string Tylko do odczytu. Identyfikator encji. Jeśli formularz jest w trybie edycji
ObjectTypeCode string Tylko do odczytu. Kod typu encji którą edytujemy/wyświetlamy na formularzu
ObjectTypeName string Tylko do odczytu.  Nazwa typu encji której dotyczy formularz
all.{field name}  Kolekcja poszczególnych pól formularza odpowiadającym polom w encji lub IFRAME formularza.

Przykład

[js]

var CRM_FORM_TYPE_CREATE = 1;
var CRM_FORM_TYPE_UPDATE = 2;

// Test the FormType and ObjectId properties.
switch (crmForm.FormType)
{
case CRM_FORM_TYPE_CREATE:
alert("This is a create form.");
break;

case CRM_FORM_TYPE_UPDATE:
alert("This is an update form, the ID is " + crmForm.ObjectId + ".");
break;
}
[/js]
[js]
var CRM_ENTITY_ACCOUNT = 1;
var CRM_ENTITY_CONTACT = 2;

// Test the ObjectTypeCode property.
switch (crmForm.ObjectTypeCode)
{
case CRM_ENTITY_ACCOUNT:
alert("This is an Account form.");
break;

case CRM_ENTITY_CONTACT:
alert("This is a Contact form.");
break;
}

[/js]

Żródło: http://msdn.microsoft.com/en-us/library/cc150873.aspx