Konkurs – vouchery na egzamin - pytania

Tak jak wczoraj pisaliśmy, dzisiaj publikujemy dwadzieścia pytań związanych z egzaminami, do których w ciągu ostatnich trzech miesięcy publikowaliśmy artykuły przygotowujące. Pytania są zamknięte i pierwsza osoba, która w komentarzu (przypominamy o poprawnym podaniu adresu email, na który wyślemy vouchery) poda poprawną odpowiedz na wszystkie pytania otrzyma nagrodę voucher na egzamin oraz voucher na kurs e-learningowy ASP.NET 3.5. Poniżej lista pytań:

70-562 – ASP:

  1. Masz DataSet zawierającego Customer DataTable oraz Order DataTable. Chcesz łatwo przechodzić z Order DataRow do Customer, który jest autorem zamówienia. Który obiekt umożliwi Ci łatwe przechodzenie z obiektów Order do obiektów Customer?

    A. DataColumn

    B. DataTable

    C. DataRow

    D. DataRelation

  2. Która z poniższych metod klasy HttpServerUtility może zostać użyta to przejścia na inną stronę aplikacji bez przesyłania o tym informacji do klienta:

    A. Redirect

    B. MapPath

    C. Transfer

    D. UrlDecode

  3. Potrzebujesz przechowywać dane, które są dostępne dla każdego użytkownika, który odwiedza Twoją stronę. Jakiej kolekcji powinieneś użyć w tym celu?

    A. Session

    B. Application

    C. Cookies

    D. ViewState

  4. Co musisz dodać do connection stringa, aby umożliwić dostęp do danych asynchroniczny?

    A. BeginExecute=true

    B. MultiThreaded=true

    C. MultipleActiveResultSets=true

    D. Asynchronous Processing=true

  5. Potrzebujesz generować dynamicznie dokumenty Worda, kiedy po aplikacji przychodzi żądanie pobrania pliku, którego rozszerzeniem jest .docx. Jak możesz to zrobić?

    A. Zaimplementować interfejs IPartitionResolver

    B. Zaimplementować interfejs IHttpModule

    C. Zaimplementować interfejs IHttpHandler

    D. Zaimplementować interfejs IHttpHandlerFactory

  6. Której klasy użyjesz podczas konwersji między typami danych .NET Framework a typami XML?

    A. XmlType

    B. XmlCast

    C. XmlConvert

    D. XmlSettings

  7. Tworzysz aplikację webową w ASP.NET w dziesiątkami stron wchodzących w jej skład. Chcesz zapisać preferencje użytkownika, tak aby można było się do tych informacji dostać z każdej strony. Dodatkowo chcesz, aby te ustawienia były zapamiętywany między kolejnymi wizytami użytkownika, nawet jak zamknie przeglądarkę. Który mechanizm zapamiętywania stanu po stronie klienta użyjesz?

    A. View state

    B. Control state

    C. Hidden fields

    D. Cookies

    E. Query strings

  8. Jaki tym uwierzytelniania na poziomie aplikacji musicie skonfigurować, aby móc skorzystać z domyślnego membership providera – AspNetSqlMembershipProvider?

    A. Windows

    B. Forms

    C. Passport

    D. None

  9. Potrzebujesz dynamicznie zmienić master page dla strony. W którym zdarzeniu strony to zrobisz?

    A. Page_Load

    B. Page_Render

    C. Page_PreRender

    D. Page_PreInit

  10. Chcesz napisać serwis WCF, który będzie hostowany przez IIS. Który typ projektu powinieneś użyć?

    A. WCF Service library

    B. WCF Service application

    C. ASP.NET Web Service application

    D. Windows Service

70-503 – WCF:

  1. Mamy klasę: 
    [ServiceBehavior()]
    public class ServiceImplementation : IServiceInterface
    {
        private int hitCounter;
        public void Increment()
        {
            hitCounter++;
        }
    }

    Jak należy udekorować klasę ServiceImplementation aby problemy współbieżności zostały wyeliminowane bez dodawania kodu w klasie? (Wybierz wszystkie poprawne odpowiedzi)

    A. ConcurrencyMode=Multiple i InstanceContextMode=Single

    B. ConcurrencyMode=Single i InstanceContextMode=PerSession

    C. ConcurrencyMode=Multiple i InstanceContextMode=PerSession

    D. ConcurrencyMode=Single i InstanceContextMode=Single

  2. Który z poniższych punktów rozszerzenia (po stronie serwisu) musi być też zaimplementowany po stronie klienta?

    A. Message Inspection

    B. Message Formatting

    C. Parameter Inspection

    D. Operation Invoker

  3. W obiekcie wiadomości właściwość MessageState jest ustawiona na Written. Które z poniższych zdarzeń zaszło?

    A. Metoda GetReaderAtBodyContents została wywołana.

    B. Metoda WriteBodyContents została wywołana.

    C. Metoda CreateBufferedCopy została wywołana.

    D. Metoda CreateMessage została wywołana.

  4. Właśnie definiujesz nowy kontrakt serwisu. Które z poniższych reprezentują atrybuty z przestrzeni System.ServiceModel, które na pewno będą potrzebne?

    A. ServiceContractAttribute i FaultContractAttribute

    B. OperationContractAttribute i FaultContractAttribute

    C. ServiceContractAttribute i OperationContractAttribute

    D. OperationContractAttribute i MessageParameterAttribute

  5. Będziesz obsługiwać serwis napisany w javie. Które z poniższych są poprawnymi metodami utworzenia proxy WCF do obsługi serwisu? (Wybierz wszystkie poprawne)

    A. Użyj klasy ChannelFactory class do utworzenia obiektu proxy dynamicznie.

    B. Użyj polecenia svcutil do utworzenia obieku proxy na podstawie definicji WSDL

    C. Ręcznie utwórz klasę proxy dziedziczącą po ClientBase.

    D. Dodaj referencję serwisu w Visual Studio (dodając referencję WSDL serwisu do projektu).

  6. Potrzebujesz uruchomić serwis na serwerze IIS. Która wersja IIS obsługuje protokoły nie-HTTP?

    A. IIS 5.1

    B. IIS 6.0

    C. IIS 7.0

    D. Żadna z wersji IIS

  7. Utworzyłeś aplikację kliencką WCF, która musi obsługiwać wywołanie zwrotne z serwisu. Który z bindingów użyjesz aby spełnić to wymaganie?

    A. basicHttpBinding

    B. wsHttpBinding

    C. wsHttpContextBinding

    D. wsDualHttpBinding

  8. Utworzyłeś aplikację kliencką WCF, która musi obsługiwać wywołanie zwrotne z serwisu. Który z poniższych bindingów NIE wspiera tego wymagania?

    A. netTcpBinding

    B. netNamedPipeBinding

    C. netMsmqBinding

    D. netTcpContextBinding

  9. Jaki będzie rezultat poniższego kodu?
    using (TransactionScope ts1 = new TransactionScope(
        TransactionScopeOption.Required, 
        new Timespan(0, 0, 30)))
    {
        using (TransactionScope ts2 = new TransactionScope(
            TransactionScopeOption.Required, 
            new Timespan(0, 0, 40)))
        {
            // Update database
            // Sleep for 35 seconds
            ts2.Complete();
        }
        ts1.Complete();
    }

    A. Obie transakcje zostaną zatwierdzone.

    B. Obie transakcje zostaną wycofane.

    C. Transakcja ts2 zostanie zatwierdzona a ts1 wycofana.

    D. Transakcja ts1 zostanie zatwierdzona, a ts2 wycofana.

  10. Masz aplikację Windows Forms. W pojedynczej transakcji Twoja aplikacja musi zaktualizować dwie bazy Microsoft SQL Server. Który koordynator transakcji zarządza tymi transakcjami?

    A. Lightweight Transaction Manager

    B. Microsoft Distributed Transaction Controller

    C. Kernel Transaction Manager

    D. Web Services Transaction Manager

Powodzenia!

Tagi: , , , , , ,

Konkurs – vouchery na egzamin

Tak jak zapowiadaliśmy wcześniej, mamy dla Was niespodziankę!

Mamy do rozdania kilka nagród:

  • 2 vouchery na dowolny egzamin (ważne do 30 lipca 2010)
  • 2 vouchery na kurs e-learningowy 6364: Visual Studio 2008 ASP.Net 3.5 (ważne do 30 czerwca 2010)

Chcieliśmy podziękować Olsztyńskiej Grupie IT za vouchery. Dzięki!!!

Konkurs na najlepszą “zajawkę”

Waszym zadaniem jest napisanie notki z linkami (70-536, 70-562, 70-503) do naszych kursów w jakimś blogu/serwisie. Najlepsza “zajawka” będzie nagrodzona: voucherem na egzamin, a kolejna voucherem na kurs e-learningowy.

Termin zgłaszania “zajawek” (termin wpisania linku do nich w komentarzach) godz. 12.00, poniedziałek 14 czerwca 2010 r!

Konkurs na najszybszego czytelnika

Jutro (piątek 11 czerwca 2010) o godzinie 12.00 pojawią się 20 pytania z zakresu przedstawianych przez nas kursów (dziesięć z WCF, dziesięć z ASP.NET).

Najszybsza osoba, która wpisze w komentarzu poprawne odpowiedzi na wszystkie pytania otrzyma voucher na egzamin i voucher na kurs e-learningowy.

Skrócony regulamin:
  • nagrody nie podlegają wymianie na ich wartość pieniężną
  • wszelkie konflikty rozwiązuje oraz “zajawki” ocenia komisja w składzie: Daniel Plawgo, Dawid Cieszyński, Kamil Lemański, Daniel Jarzynka, Dawid Tulski
  • członkowie komisji nie mogą brać udziału w konkursach
  • do komunikacji z zwycięzcami będzie użyty adres email pozostawiony w komentarzu

Tagi: , , , , , ,

Podsumowanie wpisów przygotowujących do egzaminu 70-536

Jak zapewne zauważyłeś od jakiegoś czasu trzy razy w tygodniu pojawiały się wpisy, których tytuły zaczynały się od 70-536. Kamil Lemański, Daniel Jarzynka oraz Dawid Tulski przygotowując się do tego egzaminu tworzyli wpisy podsumowujące kolejne lekcje z Training Kita. W tym miejsu zebrałem wszystkie artykuły, które się pojawiły (pojawiły się już wszystkie lekcje z drugiej edycji książki):

  1. Podstawy Frameworku
    1. Użycie typów wartościowych
    2. Użycie popularnych typów referencyjnych
    3. Tworzenie klas
    4. Konwersja między typami danych
  2. Wejście/Wyjście
    1. Praca z systemem plików
    2. Czytanie oraz pisanie do plików i strumieni
  3. Wyszukiwanie, modyfikowanie oraz kodowanie napisów
    1. Formatowanie wyrażeń reguralnych
    2. Kodowanie i dekodowanie
  4. Kolekcje oraz typy generyczne
    1. Kolekcje oraz słowniki
    2. Kolekcje generyczne
  5. Serializacja
    1. Serializowanie obiektów
    2. Serializacja XML
    3. Serializacja niestandardowa
  6. Grafika
    1. Rysowanie grafiki
    2. Praca z obrazami
    3. Formatowanie tekstów
  7. Wątki
    1. Uruchamianie wielu wątków
    2. Zarządzanie wątkami
  8. Domena aplikacji oraz usługi
    1. Tworzenie domeny aplikacji
    2. Konfiguracja domeny aplikacji
    3. Tworzenie usług windows
  9. Instalacja oraz konfiguracja aplikacji
    1. Konfiguracja aplikacji
    2. Konfiguracja .NET Framework
    3. Instalacja aplikacji
  10. Logowanie oraz zarządzanie systemem
    1. Logowanie stanu aplikacji
    2. Praca z licznikami wydajności
    3. Zarządzanie komputerami
  11. Zabezpieczenia aplikacji
    1. Zrozumieć CAS
    2. Używanie deklaratywnych zabezpieczeń w celu ochrony Assemblies
    3. Używanie deklaratywnych oraz bezględnych metod ochrony metod
  12. Zabezpieczenia użytkowników oraz danych
    1. Uwierzytelnianie oraz autoryzacja użytkowników
    2. Używanie listy kontroli dostępu
    3. Szyfrowanie oraz deszyfrowanie danych
  13. Interoperacyjności z użyciem COM
    1. Użycie komponentów COM w .NET Framework
    2. Użycie typów .NET w aplikacja COM
  14. Reflekcja
    1. Użycie refleksji
  15. Mail
    1. Tworzenie wiadomości e-mail
    2. Wysyłanie e-maili
  16. Globalizacja
    1. Formatowanie danych za pomocą mechanizmu globalizacji

Planujemy też w najbliższym czasie ruszyć z podobnymi wpisami z innych egzamów ale jeszcze nie zdecydowaliśmy się na jakiś konkretny. Może Ty chciałbyś, aby z jakiegoś egzaminu pojawiały się wpisy? Jeśli tak to zostać info w komentarzu :)

Tagi: , , ,

70-536 Globalization

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

Globalizacja to proces tworzenia aplikacji która wspomaga nasz “lokalny” interfejs. Przez lokalny należy rozumieć kulturę wyświetlania liczb, dat czy innych informacji. .NET Framework jest w stanie zrobić większość rzeczy za użytkownika, my jednak musimy zrozumieć jak korzystać z przewidzianych narzędzi. Na przykład w Stanach Zjednoczonych separatorem “miejsc po przecinku” (mówiąc po polsku ;) )jest kropka.

Ustawienia kultury

Możemy użyć dwóch właściwości do ustawienia kultury z jakiej chcemy skorzystać w naszym programie.

Thread.CurrentThread.CurrentCulture – nie można tutaj ustawić neutralnej kultury, określić samego języka w obiekcie CurrentCulture typu fr, en tylko trzeba wybrać ze zdefiniowanych kultur zarówno język jak i regionalne formatowanie typu fr-FR.

oraz

Thread.CurrentThread.CurrentUICulture - Określa, jakie zasoby są ładowane przez Resource Manager, jeśli przewidziane są środki w wielu językach. Ponieważ ten kontroluje tylko w jakim języku są używane, można zdefiniować CurrentUICulture z obu kultur neutralnie lub wyszczególnione.

Rozważmy następujący kod:

   1: //C#
   2: // Change the current culture
   3: Thread.CurrentThread.CurrentCulture = new CultureInfo("es-ES");
   4: Thread.CurrentThread.CurrentUICulture = new CultureInfo("es-ES");
   5: MessageBox.Show(Thread.CurrentThread.CurrentCulture.ToString());
   6: double d = 1234567.89;
   7: // Show the figure as currency using the current culture
   8: MessageBox.Show(d.ToString("C"));
   9: // Show the current time using the current culture
  10: MessageBox.Show(DateTime.Now.ToString());

 

Ten kod przykładowy tworzy następujące dane wyjściowe dla kultury es-ES:

es-ES
1.234.567,89 €
17/08/2008 11:07:46

W poprzednim przykładzie na sztywno wpisaliśmy kulturę do naszego kodu. Jeśli jednak mamy przetłumaczoną aplikacje na język niemiecki, hiszpański i angielski to musimy użytkownikowi dać do wyboru tylko jeden z trzech języków. Można także pobrać tablicę wszystkich dostępnych kultur, wywołując metodę System.Globalization.CultureInfo.GetCultures. Oraz z typu wyliczeniowego CultureTypes wybrać interesujące nas kultury. Najbardziej przydatne wartości z CultureTypes:

AllCultures- wszystkie kultury które przewidziano w .NET Framework

NeutralCultures- neutralna kultura która zapewnia tylko język a nie formatowanie danych.

SpecificCultures- wyszczególniona kultura, język + formatowanie danych

Jak formatować dane wyjściowe z różnych kultur

Poniższy kod demonstruje wyświetlanie instancji DateTime w różnych kulturach.

   1: // C#
   2: // Display the current time using the default culture
   3: Console.WriteLine(DateTime.Now.ToString());
   4: // Display the current time using the English-Great Britain culture
   5: Console.WriteLine(DateTime.Now.ToString(new CultureInfo("en-GB")));
   6: // Display the current time using the Russian culture
   7: Console.WriteLine(DateTime.Now.ToString(new CultureInfo("ru-RU")));

 

Zakładając, że komputer  domyślnie jest ustawiony na en-US, poprzedni kod daje następujący wynik:

8/17/2008 10:06:31 PM
17/08/2008 20:06:31
17.08.2008 20:06:31

Zwróćmy uwagę na następujące rzeczy:

W kulturze en-US data wyświetlana jest w formacie mm/dd/yyyy i czas AM/PM

W kulturze en-GB data wyświetlana jest w formacie dd/mm/yyyy

W kulturze ru-RU data wyświetlana jest w formacie dd.mm.yyyy

Rozważmy teraz wyświetlanie walut dla tych samych kultur:

   1: // C#
   2: double d = 1234567.89;
   3: // Show the figure as currency using the default culture
   4: Console.WriteLine(d.ToString("C"));
   5: // Show the figure as currency using the English-Great Britain culture
   6: Console.WriteLine(d.ToString("C", new CultureInfo("en-GB")));
   7: // Show the figure as currency using the Russian culture
   8: Console.WriteLine(d.ToString("C", new CultureInfo("ru-RU")));

 

Analogicznie do poprzedniego przykładu i poprzednich kultur uzyskamy:

$1,234,567.89
£1,234,567.89
1 234 567,89p.

Ja sformatować dane ręcznie?

Jeśli chcemy edytować dane ręcznie musimy uzyskać informacje o danej kulturze, sposobie formatowania przy użyciu np. CultureInfo.NumberFormat lub CultureInfo.DateTimeFormat. Poniższy kod pokazuje jak używać NumberFormat.Number-DecimalSeparator, NumberFormat.NumberGroupSizes, i NumberFormat.NumberGroupSeparator do wyświetlania długich liczb.

   1: // C#
   2: public static void Main()
   3: {
   4: FormatData(new CultureInfo("es-ES"));
   5: FormatData(new CultureInfo("ru-RU"));
   6: FormatData(new CultureInfo("en-US"));
   7: Console.ReadKey();
   8: }
   9: private static void FormatData(CultureInfo ci)
  10: {
  11: // Display the selected culture
  12: Console.WriteLine(ci.ToString() + ":");
  13: // Identify the number and copy it to a string
  14: double d = 1234567.89;
  15: string formattedNumber = d.ToString();
  16: // Identify the location of the culture-sensitive decimal point in the number
  17: int decimalIndex = formattedNumber.IndexOf(
  18: Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator) + 1;
  19: // Extract only the decimal portion of the number
  20: formattedNumber = formattedNumber.Substring(
  21: decimalIndex, formattedNumber.Length - decimalIndex);
  22: // Add the culture-specific decimal point before the number
  23: formattedNumber = ci.NumberFormat.NumberDecimalSeparator + formattedNumber;
  24: // Extract only the whole portion of the number
  25: string wholeDigits = Math.Floor(d).ToString();
  26: // Add each whole digit to formattedNumber, with grouping separators
  27: for (int a = 0; a < wholeDigits.Length; a++)
  28: {
  29: // Examine CultureInfo.NumberFormat.NumberGroupSizes to determine
  30: // whether the current location requires a separator
  31: bool requiresSeparator = false;
  32: foreach (int sep in ci.NumberFormat.NumberGroupSizes)
  33: {
  34: if ( (a > 0) && ((a % sep) == 0) )
  35: {
  36: requiresSeparator = true;
  37: }
  38: }
  39: // Add a separator if required
  40: if (requiresSeparator)
  41: {
  42: formattedNumber = ci.NumberFormat.NumberGroupSeparator + formattedNumber;
  43: }
  44: // Add the number to the final string
  45: formattedNumber =
  46: wholeDigits.ToCharArray()[wholeDigits.Length - a - 1] + formattedNumber;
  47: }
  48: // Display the manual results and the automatically formatted version
  49: Console.WriteLine(" Manual: {0}", formattedNumber);
  50: Console.WriteLine(" Automatic: {0}", d.ToString("N", ci));
  51: }

Dane wyjściowe:

es-ES:
Manual: 1.234.567,89
Automatic: 1.234.567,89
ru-RU:
Manual: 1 234 567,89
Automatic: 1 234 567,89
en-US:
Manual: 1,234,567.89
Automatic: 1,234,567.89

Sortowanie i porównywanie obiektów

Mamy świadomość, że w zależności od kultury inaczej sortuje się alfabet (bo np. mogą występować różne specyficzne znaki) czy też będzie brana pod uwagę wielkość liter. Poniższy przykład pokazuje to na przykładzie znaku Æ dla dwóch kultur:

   1: // C#
   2: public static void Main()
   3: {
   4: string[] words = new string[] { "Apple", "Æble" };
   5: Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
   6: SortWords(words);
   7: Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
   8: SortWords(words);
   9: }
  10: private static void SortWords(string[] words)
  11: {
  12: Console.WriteLine(Thread.CurrentThread.CurrentCulture);
  13: Array.Sort(words);
  14: foreach (string s in words)
  15: {
  16: Console.WriteLine(s);
  17: }
  18: }

 

Na ekranie konsoli w wyniku dostaniemy:

en-US
Æble
Apple
da-DK
Apple
Æble

W traning kit jest ładna tabelka która pokazuje kultury obsługujące różne sortowania etc.

To tyle w tym temacie. Więcej informacji można znaleźć w traning kit a dokładnie mówiąc m.in opis wielu właściwości dla kultur…jest tego chyba z 3 strony oraz krótki opis jak stworzyć własną kulturę. Tym artykułem również kończymy na naszej stornie cykl artykułów przygotowujących do egzaminu 70-536. Artykuły te należy traktować jako ostatnie przypomnienie najważniejszych informacji przed samym egzaminem. Dzięki wszystkim którzy czytali artykuły, dzielili się swoimi uwagami i spostrzeżeniami. 

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

Tagi: , , ,

70-536: Sending E-mail

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

Jak wysłać wiadomość

Po utworzeniu wiadomości, musimy wysłać ją przez serwer SMTP, który prześle  wiadomość do odbiorcy. W .NET klasą, która reprezentuje serwer SMTP jest klasa SmtpClient. Aby wysłać wiadomość wywołujemy SmtpClient.Send. Najczęściej wysyłanie wiadomości jest tak proste jak w poniższym przykładzie(gdzie smtp.contoso.com jest nazwą lokalnego serwera SMTP):

   1: MailMessage m = new MailMessage
   2:    ("jane@northrup.org",
   3:     "ben@northrup.org",
   4:     "Quarterly data report.",
   5:     "Hello, world.");
   6: SmtpClient client = new SmtpClient("smtp.contoso.com");
   7: client.Send(m);

 

Obsługiwanie wyjątków E-mail

Podczas wysyłania wiadomości, wiele rzeczy może pójść nie tak. Na przykład: serwer może nie być dostępny, serwer może odrzucić poświadczenia użytkownika itp. W każdym takim przypadku runtime rzuca wyjątkiem a my musimy tak przygotować naszą aplikację, żeby ten wyjątek złapała i obsłużyła.

Kiedy wysyłamy wiadomości, powinniśmy być zawsze przygotowani na złapanie wyjątku SmtpException.
Wiadomości często są odrzucane ponieważ np. nie można odnaleźć serwera smtp, serwer identyfikuje wiadomość jako spam itd.
Powinniśmy również obsługiwać wyjątek SmtpFailedRecipientException, który runtime rzuca jeśli serwer smtp odrzuca email odbiorcy.
Poniższa tabelka podsumowuje wyjątki, które mogą być rzucone podczas pracy z mailami:

 

Sytuacja Wyjątek
Nie określono serwera hosta InvalidOperationException
Nazwa serwera hosta nie została znaleziona SmtpException z wewnętrznym WebException
Wysyłasz maila do odbiorcy na lokalnym serwerze ale odbiorca nie ma poczty SmtpFailedRecipientException
Niepoprawny user bądź są inne problemy z transmisją nieobjętych w innych wyjątkach SmtpException

Jak konfigurować poświadczenia

Aby zredukować spam, wszystkie serwery smtp powinny odrzucać wiadomości od nieautoryzowanych użytkowników. Serwery smtp dostarczane przez dostawców usług internetowych zwykle określają, który użytkownik jest uprawniony na podstawie jego adresu IP.
Inne serwery smtp wymagają od użytkownika dostarczenia nazwy użytkownika oraz hasła. Aby użyć domyślnych poświadczeń sieciowych, ustaw SmtpClient.UseDefaultCredentials na true. Alternatywnie można ustawić SmtpClient.Credentials na CredentialCache.DefaultNetworkCredentials, jak na poniższym przykładzie:

   1: SmtpClient client = new SmtpClient("smtp.contoso.com");
   2: client.Credentials = CredentialCache.DefaultNetworkCredentials;

Aby określić nazwę użytkownika i hasło, musimy stworzyć instancję klasy System.Net.NetworkCredential i użyć jej do zdefiniowania SmtpClient.Credentials. Poniższy przykład pokazuje zaprogramowane na stałe poświadczenia:

   1: SmtpClient client = new SmtpClient("smtp.contoso.com");
   2: client.Credentials = new NetworkCredential("user", "password");

Jak skonfigurować SSL

Inną bardzo ważną właściwością związaną z bezpieczeństwem jest SmtpClient.EnableSsl. Kiedy ustawimy tę właściwość na true, runtime  szyfruje połączenia SMTP używając SSL. Należy jednak pamiętać, że nie wszystkie serwery smtp wspierają SSL.

Jak wysyłać wiadomości asynchronicznie

Wysyłanie wiadomości e-mail często trwa mniej niż sekundę. Jednak często serwer smtp jest powolny lub w ogóle nie odpowiada. Wtedy nasza aplikacja czeka tyle ile określiliśmy w SmtpClient.Timeout. Choć aplikacja czeka wtedy na serwer smtp, użytkownik nie może robić nic w międzyczasie.
Na szczęście można wysyłać wiadomości asynchronicznie, czyli tak,  żeby użytkownik nie musiał czekać aż e-mail zostanie wysłany. Możemy również dać użytkownikowi opcję anulowania wysyłania.
Aby wysyłać wiadomość asynchronicznie należy:

1.  Stworzyć metodę SmtpClient.SendCompleted, która reaguje na zdarzenie. Metoda wymaga ustalenia czy transmisja się udała, nie udała bądź czy została anulowana.

2. Dodajemy obsługę zdarzenia SmtpClient.SendCompleted.

3. Wywołujemy SmptClient.SendAsync.

4. Jeśli chcesz udostępnić użytkownikowi anulowanie emaili, możesz to zrobić za pomocą metody SmtpClient.SendAsyncCancel.

Przykład:

   1: static void sc_SendCompleted(object sender, AsyncCompletedEventArgs e)
   2: {
   3:   if (e.Cancelled)
   4:     Console.WriteLine("Message cancelled");
   5:   else if (e.Error != null)
   6:     Console.WriteLine("Error: " + e.Error.ToString());
   7:   else
   8:     Console.WriteLine("Message sent");
   9: }

Poniższy kod tworzy obiekt SmtpClient, dodaje obsługę zdarzenia, wywołuje asynchroniczne wysyłanie a następnie natychmiast to wysyłanie anuluje. Oczywiście, w prawdziwym programie powinniśmy poczekać aż użytkownik sam anuluje wysyłanie :). Zakładamy że obiekt MailMessage o nazwie mm  już istnieje.

   1: SmtpClient sc = new SmtpClient("server_name");
   2: // Add the event handler
   3: sc.SendCompleted += new SendCompletedEventHandler(sc_SendCompleted);
   4: // Send the message asynchronously
   5: sc.SendAsync(mm, null);
   6: // Cancel the send
   7: sc.SendAsyncCancel();

SmtpClient.SendAsync akceptuje dwa parametry: obiekt MailMessage do wysłania oraz jakiś drugi, który jest obiektem wyłącznie do własnego użytku.

 

To wszystko na dzisiaj i to wszystko z mojej strony w tej serii artykułów. W środę ukaże się ostatni artykuł z serii 70-536. Dzięki za uwagę i być może do “usłyszenia” w następnej serii.

Kolejny artykuł z serii to Formatowanie danych za pomocą mechanizmu globalizacji

Tagi: , ,

70-536: Creating an E-mail Message

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

image

E-mail jest popularnym mechanizmem komunikacji. Framework .NET zawiera przestrzeń nazw System.Net.Mail, która zawiera klasy wspomagające tworzenie i wysyłanie wiadomości e-mail. W tym artykule skupimy się wyłącznie na tworzeniu wiadomości. Następna lekcja będzie o wysyłaniu.

 

Podstawowa wiadomość

Aby wysłać wiadomość należy utworzyć obiekt MailMessage, określić nadawcę, odbiorcę, tytuł (ang. subject) i treść wiadomość (ang. body). Klasa MailMessage zawiera kilka konstruktorów. Najprostszy pozwala nam utworzyć wiadomość w jednym wierszu kodu. Bardziej zaawansowane wiadomości, określenie wielu odbiorców czy dodanie załączników wymaga więcej kodu. Prosty przykład:

   1: MailMessage m = new MailMessage("from@example.com", "to@example.com", "Subject.", "Body.");

Nadawcę i odbiorcę możemy podać jako instancje obiektu MailAddress, co pozwala nam podać dodatkowo m.in. nazwę użytkownika.

Gdybyśmy chcieli ustawić wielu odbiorców należy utworzyć obiekt MailMessage bez parametrów, a następnie dodać obiekty MailAddress do właściwości MailMessage.To. Należy także ustawić pola From i Subject:

   1: MailMessage m = new MailMessage();
   2: m.From = new MailAddress("tomek@example.com", "Tomasz Raz");
   3: m.To.Add(new MailAddress("janek@test.com", "Jan Dwa"));
   4: m.To.Add(new MailAddress("ben@example.com", "Benia Trzy"));
   5: m.Subject = "Najnowsza oferta handlowa.";
   6: m.Body = "Super okazja! Kolejna promocja Viagry!";

Można ustawić także pola Cc i Bcc.

Dodajmy załącznik

W celu dodania pliku należy utworzyć instancję klasy Attachment i dodać ją do kolekcji MailMessage.Attachments. Załącznik można dodać z lokalnego systemu plików podając nazwę pliku, lub korzystając z obiektu Stream. Przykłady:

   1: MailMessage m = new MailMessage();
   2: m.Attachments.Add(new Attachment(@"C:\windows\win.ini"));

Poniższy przykład demonstruje wykorzystanie Stream a dodatkowo określanie typu MIME:

   1: MailMessage m = new MailMessage();
   2: Stream sr = new FileStream(@"C:\Attachment.txt", FileMode.Open, FileAccess.Read);
   3: m.Attachments.Add(new Attachment(sr, "myfile.txt", MediaTypeNames.Application.Octet));

Wiadomości HTML

Utworzenie wiadomości HTML sprowadza się do wstawienia kodu HTML w pole Body i ustawienia pola MailMessage.IsBodyHtml na true:

   1: MailMessage m = new MailMessage();
   2: m.From = new MailAddress("lance@contoso.com", "Lance Tucker");
   3: m.To.Add(new MailAddress("burke@contoso.com", "Burke Fewel"));
   4: m.Subject = "Testing HTML";
   5: // Ustawienie wiadomości
   6: m.Body = "<html><body><h1>My Message</h1><br>This is an HTML message.</body></html>";
   7: m.IsBodyHtml = true;
   8: // Wysłanie wiadomości
   9: SmtpClient client = new SmtpClient("smtp.contoso.com");
  10: client.Send(m);

Jeśli chcemy dodać obrazki do wiadomości musimy utworzyć obiekt klasy AlternateView oraz LinkedResource dla każdego obrazka:

   1: string htmlBody = "<html><body><h1>Picture</h1><br><img src=\"cid:Pic1\"></body></html>";
   2: AlternateView avHtml = AlternateView.CreateAlternateViewFromString(htmlBody, null, MediaTypeNames.Text.Html);
   3:  
   4: // Create a LinkedResource object for each embedded image
   5: LinkedResource pic1 = new LinkedResource("pic.jpg", MediaTypeNames.Image.Jpeg);
   6: pic1.ContentId = "Pic1";
   7: avHtml.LinkedResources.Add(pic1);
   8:  
   9: // Create an alternate view for unsupported clients
  10: string textBody = "You must use an e-mail client that supports HTML messages";
  11: AlternateView avText = AlternateView.CreateAlternateViewFromString(textBody, null, MediaTypeNames.Text.Plain);
  12:  
  13: // Add the alternate views instead of using MailMessage.Body
  14: MailMessage m = new MailMessage();
  15: m.AlternateViews.Add(avHtml);
  16: m.AlternateViews.Add(avText);
  17:  
  18: // Address and send the message
  19: m.From = new MailAddress("lance@contoso.com", "Lance Tucker");
  20: m.To.Add(new MailAddress("james@contoso.com", "James van Eaton"));
  21: m.Subject = "A picture using alternate views";
  22: SmtpClient client = new SmtpClient("smtp.contoso.com");
  23: client.Send(m);

W przykładzie można zaobserwować, że utworzonemu obiektowi pic1 przypisujemy ContentID o wartości Pic1. W treści strony odwołujemy się do niego za pomocą znacznika postaci <img src="cid:Pic1"> .
Jeśli chcemy wysłać wiadomość HTML, którą mogą przeglądać osoby, których klient poczty nie obsługuje tego formatu powinniśmy użyć klasy AlternateView. Dostarczamy wiele wersji naszej wiadomości, w tym jedną tekstową.

Kolejny artykuł z serii to 70-536: Sending E-mail

Tagi: , ,

70-536 Using Reflection

Poniższy artykuł pochodzi z serii Przygotowań do egzaminu 70-536.

Dzisiaj powiemy sobie o używaniu refleksji, tworzeniu instancji typów, wywoływanie metod do dynamicznego ładowania pakietów, ładowaniu pakietów itd.

Przez większość czasu mamy bezpośredni dostęp do typów w trakcie pisania kodu. Są jednak chwilę kiedy warto byłoby załadować assembly, typy i metody zawarte w nim dynamicznie. Na przykład aplikacja, która obsługuje wtyczki powinna być napisana tak aby uruchomić plug-in dynamicznie nawet gdy plug-in nie jest dostępny, podczas opracowywania takiego wniosku.

Jak załadować pakiet?

Możemy ładować pakiety dynamicznie (runtime). Po załadowaniu pakietu można zbadać jego atrybuty i w zależności od metody załadować go, utworzyć instancje typu lub uruchomić metodę. Oto metody których możemy użyć do załadowanie pakietu:

Assembly.Load- ładuje pakiet po nazwie zazwyczaj z Global Assembly Cache (GAC)

Assembly.LoadFile- ładuje pakiet poprzez podanie nazwy pliku

Assembly.LoadFrom- ładuje pakiet pobierając nazwę pliku lub ścieżkę

Assembly.ReflectionOnlyLoad- ładuje pakiet, zazwyczaj z GAC w reflection-only context (opisane poniżej)

Assembly.ReflectionOnlyLoadFrom- ładuje pakiet w reflection-only context poprzez podanie nazwy pliku

Załadowanie pakietu w reflection-only context pozwala na zbadanie pakietu ale nie tworzenie instancji typu lub uruchamianie metod. Dlatego warto używać tego kiedy mamy potrzebę tylko zbadania pakietu lub kody zawartego w nim. Często developerzy używają reflection-only context do zbadania czy pakiet nadaję się na inne platformy bądź inne wersje .NET Framework.

Jak utworzyć instancje i wywoływać metody?

Posłużę się tutaj kodem z training kit’a który jest dobrze po komentowany. Demonstruj on jak stworzyć instancje StringBuilder i wywołać metodę StringBuilder.Append przy użyciu refleksji.

   1: // C#
   2: // Create a Type instance.
   3: // Typically, this would be done by loading an external assembly,
   4: // and then calling Assembly.GetType()
   5: Type t = typeof(StringBuilder);
   6: // Create a ConstructorInfo instance that will allow us to create an
   7: // instance of the Type we just loaded.
   8: // GetConstructor requires a list of parameters in a Type array
   9: // that match those required by the constructor.
  10: // This example represents the StringBuilder constructor that
  11: // requires a single parameter.
  12: ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(string) });
  13: // Create an instance of the type by calling ConstructorInfo.Invoke.
  14: // Provide the parameters required by the constructor: a single string.
  15: // This creates a StringBuilder instance.
  16: Object sb = ci.Invoke(new Object[] { "Hello, " });
  17: // Create a MethodInfo instance representing the StringBuilder.Append method.
  18: // GetMethod requires the first parameter to be the name of the method.
  19: // The second parameter is a Type array representing the parameters required
  20: // by the method. We're using the Append overload that requires a single string.
  21: MethodInfo sbAppend = t.GetMethod("Append", new Type[] { typeof(string) });
  22: // Call StringBuilder.Append and provide a single parameter: the string "world!".
  23: Object result = sbAppend.Invoke(sb, new Object[] { "world!" });
  24: // Write the StringBuilder instance to the console.
  25: Console.WriteLine(result);

Po utworzeniu instancji MethodInfo można wywołać MethodInfo.GetMethodBase do pobrania instancji MethodBody. Następnie możemy wywołać MethodBody.GetILAsByteArray do pobrania tablicy bajtów zawierającą rzeczywisty kod pośredni (IL), kod do uruchomienia metody. MethodBody.LocalVariables jest zbiorem zmiennych lokalnych (choć nie można pobierać wartości lub nazwy zmiennych).

Dostęp do właściwości, pól, konstruktorów możemy uzyskać przy pomocy metod Type.GetProperty,Type.GetField, i Type.GetConstructors które zwracają odpowiednio PropertyInfo, FieldInfo ,i  ConstructorInfo. Działają one w niemal identyczny sposób jak Type.GetMethod.

Poniższy przykład ilustruje wykorzystanie refleksji, aby uzyskać dostęp do wartości StringBuilder.Length (tylko do odczytu) i wyświetlanie tej wartości w konsoli:

   1: // C#
   2: Type t = typeof(StringBuilder);
   3: ConstructorInfo ci = t.GetConstructor(new Type[] { typeof(string) });
   4: Object sb = ci.Invoke(new Object[] { "Hello, world!" });
   5: // Create a PropertyInfo instance representing the StringBuilder.Length property.
   6: PropertyInfo lengthProperty = t.GetProperty("Length");
   7: // Retrieve the Length property and cast it to the native type.
   8: int length = (int)lengthProperty.GetValue(sb, null);
   9: Console.WriteLine(length.ToString());

Aby przeglądać zdarzenia, pola, właściwości i metod na raz, musimy wywołać Type.GetMembers. Aby np. pobrać tylko prywatne składowe i statyczne (lub inne) musimy do tego celu wykorzystać typ wyliczeniowy BindingFlags. Spójrzmy na przykład:

   1: // C#
   2: Type t = typeof(Console);
   3: MemberInfo[] mi = t.GetMembers(
   4: BindingFlags.NonPublic | BindingFlags.Static);
   5: foreach (MemberInfo m in mi)
   6: {
   7: Console.WriteLine("{0}: {1}", m.Name, m.MemberType);
   8: }

BindingFlag oferuje następujące opcje które możemy połączyć logicznymi operatorami:

DeclaredOnly – ignoruje składowe dziedziczone

Default – nie określa w ogóle BindingFlag

FlattenHierarchyzwraca składowe dziedziczone oraz chronione

Instance- składowe które są częścią typu i są dodawane

Oraz IgnoreCase, NonPublic, Public, Static – to raczej jasne.

 

Assembly Attributes

Assembly attributes opisują nasz pakiet np. nazwe, wersje, autora itd… Zazwyczaj atrybuty dodajemy w pliku AssemblyInfo w projekcie, który początkowo zawiera domyślne ustawienia dla wielu atrybutów. Plik AssemblyInfo zawiera (miedzy innymi) domyślnie:

[assembly: AssemblyCompany("Contoso, Inc.")]
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyVersion("1.0.0.0")]

Możemy dodać następujące atrybuty do naszego pakietu (ze względu na to, że nie widziałem w traning kit po tym rozdziale szczegółowych pytań do poszczególnych atrybutów wymienię je tylko a nadgorliwi w razie potrzeby znajdą co konkretny atrybut opisuje):

AssemblyAlgorithmId, AssemblyCompany, AssemblyConfiguration, AssemblyCopyright, AssemblyCulture, AssemblyDefaultAlias, AssemblyDelaySign, AssemblyDescription, AssemblyFileVersion, AssemblyFlags, AssemblyInformationalVersion, AssemblyKeyFile, AssemblyKeyName, AssemblyProduct, AssemblyTitle,
AssemblyTrademark, AssemblyVersion.

Możemy wczytać atrybuty wywołując metodę Assembly.GetCustomAttributes która zwróci tablice obiektów typu Attribute. Iterując po niej możemy wypisać interesujące nas informacje. Oto przykład:

   1: // C#
   2: Assembly asm = Assembly.GetExecutingAssembly();
   3: foreach (Attribute attr in asm.GetCustomAttributes(false))
   4: {
   5: if (attr.GetType() == typeof(AssemblyCopyrightAttribute))
   6: Console.WriteLine("Copyright: {0}",
   7: ((AssemblyCopyrightAttribute)attr).Copyright);
   8: if (attr.GetType() == typeof(AssemblyCompanyAttribute))
   9: Console.WriteLine("Company: {0}",
  10: ((AssemblyCompanyAttribute)attr).Company);
  11: if (attr.GetType() == typeof(AssemblyDescriptionAttribute))
  12: Console.WriteLine("Description: {0}",
  13: ((AssemblyDescriptionAttribute)attr).Description);
  14: }

Generating Types Dynamically

Możemy dynamicznie tworzyć klasy przy pomocy klas z przestrzeni nazw System.Reflection.Emit. Możemy stworzyć nowy typ wraz z konstruktorami, metodami, polami etc. Poniższy przykład pokazuje jak stworzyć pakiet, nowy typ, dodać do niego przykładowe metody a na koniec wywołać jedną z nich która wyświetli nam klasyczne “Hello World” ;)

   1: // C#
   2: // Create an AssemblyBuilder instance
   3: AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
   4: new AssemblyName("dynAssembly"), AssemblyBuilderAccess.RunAndSave);
   5: // Create a ModuleBuilder
   6: ModuleBuilder mb = ab.DefineDynamicModule("dynMod");
   7: // Create a TypeBuilder public class
   8: TypeBuilder tb = mb.DefineType("dynType",
   9: TypeAttributes.Class | TypeAttributes.Public);
  10: // Create a default constructor (this isn't necessary for this example)
  11: ConstructorBuilder cb =
  12: tb.DefineDefaultConstructor(MethodAttributes.Public);
  13: // Create a public, static method named Greet that doesn't accept
  14: // parameters or return a value
  15: MethodBuilder method = tb.DefineMethod("Greet",
  16: MethodAttributes.Public | MethodAttributes.Static);
  17: // Create an ILGenerator for the method, which allows us to write code for it
  18: ILGenerator dynCode = method.GetILGenerator();
  19: // Add a line of code to the method, equivalent to Console.WriteLine
  20: dynCode.EmitWriteLine("Hello, world!");
  21: // Add a line of code to return from the method
  22: dynCode.Emit(OpCodes.Ret);
  23: // Create an instance of the dynamic type
  24: Type myDynType = tb.CreateType();
  25: // Call the static method we dynamically generated
  26: myDynType.GetMethod("Greet").Invoke(null, null);

Kolejny artykuł z serii to 70-536: Creating an E-mail Message

Tagi: , ,

Eastgroup.pl na facebooku