środa, 10 października 2012

MS SQL baza dancyh bez pliku loga

Chcąc dołączyć do MS SQL bazę która nie posiada pliku loga poprzez Management Studio zostanie wyrzucony błąd braku tego pliku.

Aby dołączyć bazę bez pliku logu można skorzystać z polecenia:

sp_attach_single_file_db @dbname= 'databasename', @physname= 'sciezka_do_pliku_mdf'

niedziela, 7 października 2012

Tworzenie i zwalnianie DbContext w aplikacji ASP.NET MVC

Korzystając z aplikacji ASP.NET MVC i EntityFrameworka warto stworzyć uniwersalny kod pobierania i zwalniania DbContex.

Przejdę od razu do implementacji:
Code:
    public static class MvcContext
    {
        public const string ContextName = "DatabaseContext";

        public static DatabaseContext Current
        {
            get
            {
                if (HttpContext.Current.Items[ContextName] == null)
                {
                    HttpContext.Current.Items[ContextName] = new DatabaseContext();
                }

                return (DatabaseContext)HttpContext.Current.Items[ContextName];
            }
        }
    }

Plik Global.asax:

Code:
public class MvcApplication : System.Web.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();
        }

        protected void Application_EndRequest()
        {
            var entityContext = HttpContext.Current.Items[MvcContext.ContextName] as DatabaseContext;
            if (entityContext != null)
            {
                entityContext.Dispose();
            }
        }

        protected void Application_BeginRequest()
        {

        }
    }


Pytanie odnośnie kodu powyżej może być jedno: dlaczego DbContext nie jest tworzony w Application_BeginRequest() ?

Metody Application_BeginRequest oraz Application_EndRequest wywoływane są przy każdym żądaniu. Jeżeli weźmiemy stronę która ma 30 obrazków - zostałoby stworzonych 30 DbContext-tów.

W przypadku powyższego kodu DbContext zostanie stworzony tylko wtedy kiedy będzie potrzebny a zwolniony po zakończeniu żądania.

MemoryCache - prosty mechanizm cache w .NET 4.0

Tworząc w ASP.NET z pewnością mieliście styczność z klasą Cache, która umożliwia buforowanie danych do późniejszego użycia. Do tej pory byliśmy ograniczeni do aplikacji webowych. Wraz z wersją .NET 4.0 dodano obsługę buforowania dla wszystkich rodzajów aplikacji (Windows Forms, WPF itd.).

Obsługa bufora jest bardzo prosta:

Code:
            var key = "klucz";
            var value = "value";
            var memoryCache = MemoryCache.Default;
            var cachePolicy = new CacheItemPolicy();
            cachePolicy.SlidingExpiration = TimeSpan.FromMinutes(1);
            memoryCache.Add(key, value, cachePolicy);

            var valueFromCache = memoryCache[key];
            if (valueFromCache == null)
            {
                memoryCache[key] = value;
            }

Powyższy kod oznacza, iż jeżeli wartość nie zostanie pobrana w ciągu minuty od jej umieszczenia tam, zostanie skasowana.

Oprócz SlidingExpiration mamy do dyspozycji AbsoluteExpiration:

Code:
cachePolicy.AbsoluteExpiration = DateTime.Now.AddMinutes(1);

oznacza on dokładną datę kiedy obiekt zostanie usunięty z bufora.

Do dyspozycji zostały nam oddane także dwa monitory:
  • SqlChangeMonitor - sprawdzający zmiany w bazie danych
  • HostFileChangeMonitor - sprawdza czy pod podanymi ścieżkami plików/folderów dokonano zmian

Innymi przydatnymi cechami bufora są:
  • możliwość ustalenia rozmiaru bufora
  • możliwość opróżnienia bufora - według procentów
  • dwa zdarzenia: UpdateCallback oraz RemovedCallback

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>