piątek, 5 października 2012

Łatwiejsze ścieżki w MVC 4

Do tej porty w ASP.NET MVC korzystaliśmy z następującej składni:

Code:
<script src="@Url.Content("~/Scripts/Site.js")"></script>


W nowej wersji jest możliwe użycie skróconej wersji:

Code:
<script src="~/Scripts/Site.js"></script>


Bundling and Minification

Tytuł ściśle związany z minimalizacją - zarówno pod względem wielkości przesyłanych danych jak i szybkością ładowania strony.

W nowej wersji MVC zostały dodane mechanizmy zwiększające wydajność ładowania JavaScript oraz stylów CSS. Jest to kontynuacja motta "Konwencja nad konfiguracją" - brak wymagania konfiguracji. Mimo braku potrzeby konfiguracji mechanizmu - jest on w pełni konfigurowalny jaki i rozszerzalny.

W jaki sposób działa mechanizm?

Jeżeli spojrzymy do eksploratora projektu nowego projektu, znajdziemy folder zawierający pliki JavaScript jak również folder gdzie znajdują się style CSS:



Uruchamiając program i badając ruch sieciowy - np w Firebug znajdziemy tam tylko dwa wpisy:


Ciekawy jest zwłaszcza pierwszy - jest to właśnie wynik miniaturyzacji i scalania wszystkich użytych skryptów w projekcie.
Kod scalający znajduje się w pliku BundleConfig:

Code:
using System.Web.Optimization;

namespace MvcApplication3
{
    public class BundleConfig
    {
        // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
                        "~/Scripts/jquery-ui-{version}.js"));

            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                        "~/Scripts/jquery.unobtrusive*",
                        "~/Scripts/jquery.validate*"));

            // Use the development version of Modernizr to develop with and learn from. Then, when you're
            // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
            bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                        "~/Scripts/modernizr-*"));

            bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));

            bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
                        "~/Content/themes/base/jquery.ui.core.css",
                        "~/Content/themes/base/jquery.ui.resizable.css",
                        "~/Content/themes/base/jquery.ui.selectable.css",
                        "~/Content/themes/base/jquery.ui.accordion.css",
                        "~/Content/themes/base/jquery.ui.autocomplete.css",
                        "~/Content/themes/base/jquery.ui.button.css",
                        "~/Content/themes/base/jquery.ui.dialog.css",
                        "~/Content/themes/base/jquery.ui.slider.css",
                        "~/Content/themes/base/jquery.ui.tabs.css",
                        "~/Content/themes/base/jquery.ui.datepicker.css",
                        "~/Content/themes/base/jquery.ui.progressbar.css",
                        "~/Content/themes/base/jquery.ui.theme.css"));
        }
    }
}


czwartek, 4 października 2012

Dependency Injection ASP MVC 4

W ASP.NET MVC 1/2 wstrzykiwanie polegało na nadpisaniu Fabryki tworzącej kontrolery. W wersji 3 i 4 wprowadzono serwis DependencyResolver. Interfejs ten zawiera dwie podstawowe metody:

Code:
  public interface IDependencyResolver
  {
    /// <summary>
    /// Resolves singly registered services that support arbitrary object creation.
    /// </summary>
    /// 
    /// <returns>
    /// The requested service or object.
    /// </returns>
    /// <param name="serviceType">The type of the requested service or object.</param>
    object GetService(Type serviceType);

    /// <summary>
    /// Resolves multiply registered services.
    /// </summary>
    /// 
    /// <returns>
    /// The requested services.
    /// </returns>
    /// <param name="serviceType">The type of the requested services.</param>
    IEnumerable<object> GetServices(Type serviceType);
  }

Warto użyć własnego kontenera rozwiązującego zależności, który oferuje znacznie więcej możliwości konfigurowania.

Użycie kontenera Unity jest bardzo proste w tym przypadku. Skorzystać można tutaj z Nuget-a.

1. Tworzymy nowy projekt ASP.NET MVC 3/4
2. Korzystając z Package Manager Console instalujemy Unity wraz z dodatkiem MVC3:

Code:
PM> Install-Package unity.Mvc3


3. Do projektu zostanie dodana klasa Bootstrapper która służy do konfiguracji naszego kontenera:

Code:
    public static class Bootstrapper
    {
        public static void Initialise()
        {
            var container = BuildUnityContainer();

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
        }

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            // register all your components with the container here
            // it is NOT necessary to register your controllers
            
            // e.g. container.RegisterType<ITestService, TestService>();            

            return container;
        }
    }


4. Kontener inicjujemy w Global.asax

Code:
    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
            Bootstrapper.Initialise();
        }
    }


To wszystko co należy zrobić aby możliwe było korzystanie z wzorca IoC w ASP.NET MVC 3/4

wtorek, 2 października 2012

Szyfrowanie Web.config

Szyfrowanie Web.config-a jest rzeczą oczywistą. Znajdują się w nim dane dostępowe do bazy danych, klucze do webserwisów oraz inne poufne dane.

Instrukcja szyfrowania Web.config-a:
1. Eksportujemy klucz maszyny (Machine key):

Code:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -px "iisConf
igurationKey" C:\folder\iisConfKey.xml -pri

Code:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -px "iisWasKey" C:\folder\iisWasKey.xml -pri


Wyeksportowany klucze znajdziemy pod ścieżką:

Code:
 C:\folder\



2. Import klucza na serwerach

Code:
c:\windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regiis.exe -pi "iisConfigurationKey" c:\folder\iisconfkey.xml -exp

Code:
c:\windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regiis.exe -pi "iisWasKey" c:\folder\iisWasKey.xml -exp


3. Autoryzacja zaimportowanego klucza

Code:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pa 
"iisConfKey"


4. Do Web.config-a dodajemy sekcję zawierającą informacje nt używanego prowidera szyfrowania:
 Jest to krok konieczny jeżeli zamierzamy używać zaimportowanego klucza na wielu serwerach:

Code:
<configprotecteddata>
<providers>
<add keyContainerName=”MyWebServerRSA”
description=”Uses RsaCryptoServiceProvider to encrypt and decrypt”
name=”MyWebServerRSAProvider”
type=”System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a” />
</providers>
</configProtectedData>


5. Przykładowe szyfrowanie sekcji connectionstringów:

Code:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pef "connection
Strings" "C:\inetpub\WebApplication1" -prov "MyWebServerRSAProvider"

Po zakodowaniu sekcja connectionStrings będzie wyglądała w następujący sposób:

Code:
    <connectionStrings configProtectionProvider="MyWebServerRSAProvider">
        <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
            xmlns="http://www.w3.org/2001/04/xmlenc#">
            <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
            <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
                    <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
                    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                        <KeyName>Rsa Key</KeyName>
                    </KeyInfo>
                    <CipherData>
                        <CipherValue>f19a64s6YB208ibupTTE6+8zWI3y+trQTAajwtpaoArJ8kLic2k0ifmmSmok3NU2Aw7vBUcR2oayzUsoJSuYIDePVr/zvI9/oMVuRMBE+nvzi598BlpZ3lxsggKiwrCO1U/h/zcgNQFuosu7PnX4Rz+4cXZB60LngaZe+Gk+jy8=</CipherValue>
                    </CipherData>
                </EncryptedKey>
            </KeyInfo>
            <CipherData>
                <CipherValue>6xZXUTJzr/ovYhI4qvw06hBA9qj59AKiOpEuwdx175R8HCiY/toW4G31GZwI237cmNTMPdlJac/VGki9C/UhU6Ehwb7VQoM8LjiqiJnWNkjyOUJYJOa+uZhpoVtEY06trjMqcFtLP/hdNiDtOwvOxusSFxGioP4Jwvfl22qTSBuc4j1QS1t8PSr/5tlZFJkSV6rxflMPJ+4Z4FYTHdfCyuk3vdnbO2RKjHyx3kNqjEz1eeKrKfz2jH9b6pbMKNss91+fE/ERjeGgdaP8wmewCw67zfjfx7B9fz/FZCw5MK+L2rUsnQMjqXCQEodVBbQtrDSGIlIAcQXGng8h2F9U09AzDSyZRrY+</CipherValue>
            </CipherData>
        </EncryptedData>
    </connectionStrings>

niedziela, 23 września 2012

Mapowanie obiektów - Extension Methods

Extension Methods można wykorzystać nie tylko do dodawania metod do istniejących klas, ale także jako najprostszy mechanizm mapujący. Nie musimy tworzyć całej biblioteki do mapowania, wystarczy dodać do klasy odpowiednią metodę np. Map.

Jako kod bazowy użyjemy obiekt encji tabeli:

Code:
    public class PersonEntity
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }

klasa którą chcemy uzyskać ma następującą strukturę:

Code:
    public class PersonView
    {
        public string FullName { get; set; }
        public string Address { get; set; }
    }

Kod mapowania:

Code:
    public static class Mappers
    {
             public static PersonView Map(this PersonEntity personEntity)
             {
                 return new PersonView
                            {
                                FullName = personEntity.FirstName + " " + personEntity.LastName,
                                Address = personEntity.Address
                            };
             }
    }

użycie sprowadza się do wywołania metody Map na obiekcie bazowym:

Code:
            var personEntity = new PersonEntity
                                   {
                                       Id = 1, Address = "Andrychowska 34, 10-124 Andrychów", Age = 31, FirstName = "Jan", LastName = "Kowalski"
                                   };
            var pv = personEntity.Map();

wtorek, 18 września 2012

TortoiseSVN Ignore dla C# i Resharper

Przydatny filtr dla ignorowanych w przypadku korzystania z Resharpera:

*\bin* *\obj* *.suo *.user *.bak **.ReSharper** **\_ReSharper.** StyleCop.Cache

Dzięki temu unikniemy komitowania folderów bin, obj i wszystkich zbędnych rzeczy - łącznie z plikami generowanymi przez Resharper.
Filtr znalazłem na blogu: Struggles by Lars C.

niedziela, 16 września 2012

jQuery selekcja

Przeglądanie drzewa DOM dokumentu HTML jest bardzo proste przy użyciu selektorów z jQuery.

$("h1") - selekcja wszystkich elementów h1
$(".klasa") - selekcja wszystkich elementów posiadających klasę klasa
$("#id_elementu") - selekcja elementu o id = id_elementu - jest to najszybszy dostępny selektor
$("*") - pobiera wszystkie elementy na stronie
$("p.klasa") - wybiera wszystkie elementy p posiadające klasę klasa
$("p:first") - wybiera pierwszy element typu p
$("[name]") - wybiera wszystkie elementy posiadające atrybut name
$("form[name='formatka1']") - wybiera wszystkie formularze o nazwie formatka1
$("a, p, div") - wyszukiwanie wielu na raz
$("div p") - wybiera wszystkie paragrafy znajdujące się w elemencie div

Metody pomocnicze:
$(".klasa").parent() - wyszukuje wszystkie elementy nadrzędne do tych o klasie klasa
$(".klasa").children() - Elementy zawarte w elementach o klasie klasa
$(".klasa").prev() / .next() - element po prawej/lewej stronie elementów o klasie klasa

Korzystając z wymienionych funkcji można w łatwy sposób zmieniać całą strukturę drzewa DOM dokumentu HTML.

Dodatkowo warto pamiętać aby każdy blok kodu jQuery rozpoczynać od sprawdzenia czy dokument został załadowany:

Code:
$(document).ready(function() {
});