Posts mit dem Label Visual Studio 2010 werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Visual Studio 2010 werden angezeigt. Alle Posts anzeigen

Samstag, 13. Juli 2013

Visual Studio Inselbuch - aktuelle Technologien für Coder

Jetzt ist es erschienen, das “Visual Studio Inselbuch”: Die Sommerlektüre für Entwickler, welche sich im Urlaub kurzweilig über neuere Technologien informieren möchten. Mein Beitrag dazu dreht sich um Near Field Communication (NFC) bei Windows Phone.

Hier der Link auf die entsprechende MSDN News.

Visual Studio Inselbuch

Sonntag, 18. April 2010

Facts of the week 18.04.2010

Diese Woche gibt es einiges zu berichten über die am Dienstag erschienen Version von Visual Studio 2010, dem neuen Resharper 5.0 und natürlich meinem Lieblingsthema dem am Freitag veröffentlichten Version 4 von Silverlight mit den dazugehörigen Tools für Visual Studio 2010 sowie den WCF RIA Services.

Visual Studio 2010

Erster Eindruck: Huch alles Lila, ist ja auch dieses Jahr eine Modefarbe. Sogar die Microsoft-Mitarbeiter tragen auf den Raodshows Lila.

Von der Oberfläche auf dem ersten Blick natürlich wieder einmal gewöhnungsbedürftig, wie bei allen neuen Sachen. Besonders schön finde ich die echte Unterstützung von mehreren Monitoren. Die Multi-Edit-Funktion ist auch nicht schlecht, gerade wenn man wieder mal mehrere Namespaces umbenennen muss.

=> Nächste Woche mehr……

Resharper 5.0

Ein Tool was ich bisher immer unterschätzt habe, aber diese Woche hat mich die Version 5.0 überzeugt. Resharper 5.0 bietet jetzt nicht nur die üblichen Codierungserleichterungen, wie “}” automatisch setzen, sondern hat zwei Features, die für sich genommen schon den Einsatz von Resharper 5.0 rechtfertigen.

Pattern Catalog unter Tools: Pattern für Suchen und Ersetzen

Jeder Entwickler hat so eine Marotten, die er immer wieder falsch macht. Bei mir ist dies z.B. die Abfrage eines Leerstrings. Neige immer dazu if (myString==””) zu kodieren, anstatt die saubere Variante string.IsNullOrEmpty($value$) zu verwenden. Für diese Unsauberkeiten kann man jetzt unter Tools im Resharper 5.0 Pattern anlegen, die einem dann der Resharper wie die anderen Regeln automatisch meldet. Klasse Sache!

Lokalisierung einfach gemacht

Eine der größten Verbrechen ist es, wenn man eine mehrsprachige Anwendung entwickeln will und die Standard-Resource-Files nutzen muß. Hier ist man nämlich normalerweise im Entwicklungsprozess gezwungen zwischen Designer bzw. Code-Editor und Resourcen-Dateinen hin un her zu springen. Das kostet unheimlich Zeit. Doch mit Resharper 5.0 ist damit nun endlich Schluß. Hier kann man einfach über einer Zeichenkette (grüner Schlingel  drunter) die rechte Maustaste drücken und dann im Kontextmenü die entsprechende Funktion aufrufen. Ressource-File aussuchen, fertig. Resharper 5.0 trägt dann die Zeichenkette mit einem generierten Key ins Ressource-File ein und setzt die Verweise darauf im Coding richtig. Das funktioniert sogar bei DataAnnotations (z.B. Fehlermeldungen bei Validierungen).

WCF RIA Services

Bei den WCF RIA Services für .NET 4.0 und Visual Studio 2010 hat sich einiges getan. Wie mittlerweile üblich bei Microsoft Produkten, wurden zum Releasetermin alle Namespaces und Assemblies überarbeitet, so dass sich vielfältige Änderungen ergeben. Darüber hinaus sind auch einige Methoden bzw. Properties weggefallen oder wurden an andere Objekte “gehängt”.

Eine Übersicht über alle Änderungen gibt es in meinem Blog  Changes of WCF RIA Services for Visual Studio 2010 | .NET - Red zone : Best practices and latest stuff. Die Informationen stammen aus einem entsprechenden Word-Dokument von Microsoft.

Changes of WCF RIA Services for Visual Studio 2010

With the new version of the WCF RIA Services for Visual Studio 2010, that comes last Friday, there are several changes.

Assemblies and Namespaces

Assembly Rename & Refactoring

Previous Assembly Name

New Assembly Name

System.Windows.Ria

System.ServiceModel.DomainServices.Client + System.ServiceModel.DomainServices.Client.Web

System.Windows.Controls.Ria

System.Windows.Controls.DomainServices

System.Web.Ria

System.ServiceModel.DomainServices.Server + System.ServiceModel.DomainServices.Hosting

System.Web.DomainServices

System.ServiceModel.DomainServices.Server

System.Web.DomainServices.EntityFramework

System.ServicesModel.DomainServices.EntityFramework

System.Web.DomainServices.LinqToSql

Microsoft.ServiceModel.DomainServices.LinqToSql

System.Web.DomainServices.Proxies

Microsoft.ServiceModel.DomainServices.Hosting.Local

System.Windows.Controls.Ria.Design

System.Windows.Controls.DomainServices.Design

System.Windows.Controls.Ria.Expression.Design

System.Windows.Controls.DomainServices.Expression.Design

System.Windows.Controls.Ria.VisualStudio.Design

System.Windows.Controls.DomainServices.VisualStudio.Design

Namespace Rename & Refactoring

Previous Namespace Name

New Namespace Name

System.Web.DomainServices

System.ServiceModel.DomainServices.Server

System.Web.DomainServices.Providers

System.ServiceModel.DomainServices.EntityFramework (for LinqToEntities classes)

Microsoft.ServiceModel.DomainServices.LinqToSql (for LinqToSql classes)

System.Web.Ria

System.ServiceModel.DomainServices.Hosting

System.Web.Ria.ApplicationServices

System.ServiceModel.DomainServices.Server.ApplicationServices

System.Web.Ria.Data

Namespace removed.

DomainIdentifierAttribute and ExternalReferenceAttribute moved to System.ServiceModel.DomainServices.

CompositionAttribute moved to System.ComponentModel.DataAnnotations.

OperationError renamed to ValidationResultInfo and now available in both System.ServiceModel.DomainServices.Client and System.ServiceModel.DomainServices.Server.

System.Web.Ria.Services

System.ServiceModel.DomainServices.Hosting

System.Windows.Controls.Ria

System.Windows.Controls

System.Windows.Data

System.Windows.Controls

System.Windows.Ria

System.ServiceModel.DomainServices.Client

System.Windows.Ria.ApplicationServices

System.ServiceModel.DomainServices.Client.ApplicationServices

System.Windows.Ria.Services

System.ServiceModel.DomainServices.Client

Changed how the Silverlight application is notified of validation errors

In the previous release, validation rules on data were enforced on the client by raising an exception when the validation rule was not met. In the RC release, validation rules are enforced by raising events through the INotifyDataErrorInfo interface, which is new in Silverlight 4. With this approach, The INotifyDataErrorInfo.ErrorsChanged event is raised when an invalid value is assigned to a property. Any where in your code that checks for a ValidationException will now likely need to change as an event is raised instead of the exception.

An overloaded version of the ValidateProperty method was added that accepts a ValidationContext parameter. The generated code was changed so this ValidateProperty method is called between the Changing and Changed events. If you want to retain exception-based validation, you can override the ValidateProperty method and raise an exception for invalid values, as shown below.

 

   1: public partial class City
   2: {
   3:     protected override void ValidateProperty(ValidationContext validationContext,
   4:     object value)
   5:     {
   6:         ValidationContext context = new ValidationContext(this, null, null) { MemberName = propertyName };
   7:         // Validate in a way that will throw an exception if invalid
   8:         System.ComponentModel.DataAnnotations.Validator.ValidateProperty(value,context);
   9:  
  10:     }
  11:  
  12: }

When you create a custom validation class or attribute, you must now pass to the Silverlight application the name or names of the members that failed validation. You pass the names back with the ValidationResult, as shown below.

 

   1: public static class GenderValidator
   2: {
   3:     public static ValidationResult IsGenderValid(string gender, ValidationContext context)
   4:     {
   5:         if (gender == "M" || gender == "m" || gender == "F" || gender == "f")
   6:         {
   7:  
   8:             return ValidationResult.Success;
   9:  
  10:         }
  11:         else
  12:         {
  13:  
  14:             return new ValidationResult("The Gender field only has two valid values 'M'/'F'", new string[] { "Gender" });
  15:         }
  16:  
  17:     }
  18:  
  19: }

Removal of Resolve methods from DomainService

In the previous release, you could provide a method for customizing how concurrency conflicts are resolved. For the RC release, this feature and all related members have been removed. Providing a common method signature for resolving conflicts in different types of DALs could not be supported in this release.

Changed server communication from SOAP with binary encoding to REST with binary encoding

In the previous release, communication between the client and server was implemented using SOAP with binary encoding. This implementation did not allow clients to cache the response because all requests were performed using POST. In the RC release, the communication has been changed to REST with binary encoding. You can now specify whether the request is performed using GET or POST. By default, queries will use GET, and invoke operations will use POST. You specify whether GET or POST is used by setting the HasSideEffects property.

To inform clients of a DomainService that they can cache a response, you must apply the OutputCache attribute to the operation.

You must rebuild existing client and server projects to accommodate this change, and add a reference to the System.ServiceModel.Web.Extensions.dll assembly in the client project. If you implemented a customized client, you will need to either change to the new protocol or implement and EndpointFactory similar to the one used in the previous release.

Changed default Endpoint for all domain services

In the RC release, by default, only the Binary endpoint is enabled for domain services. To use the Binary endpoint no additional configuration is needed. If you want to use another endpoint (such as JSON, SOAP, or a custom host) you must register an endpoint factory in the Web.config file as shown below:

 

   1: <system.serviceModel>
   2:   <domainservices>
   3:     <endpoints>
   4:       <add name="json" type="Microsoft.ServiceModel.DomainService.Hosting.JsonEndpointFactory, Microsoft.ServiceModel.DomainService.Hosting" />
   5:     </endpoints>
   6:   </domainservices>
   7:   <system.serviceModel>

Removal of ChangeSet parameter from DomainService methods

In the previous release, the AuthorizeChangeSet, ExecuteChangeSet, PersistChangeSet, and ValidateChangeSet methods on the DomainService class all contained a parameter for a ChangeSet object. The ChangeSet parameter has been removed from the methods. The parameter is not needed because the ChangeSet object is now retrieved through the ChangeSet property.

Removal of QueryCompletedResult.ResultCount Property

The ResultCount property on the QueryCompletedResult class was removed. You can retrieve the same value through the Entity.Count property.

DomainDataSource no longer blocks loads when another load is pending

In the previous release, the CanLoad property of the DomainDataSource was false when IsLoadingData is true. This implementation prevented executing a new load operation when another load was in progress. This behavior has been changed for the next release. Now, if a new load is invoked when another load is pending, the previous load is canceled and the new load supersedes it. To retain the old behavior of blocking a new load operation, check the IsLoadingData property before calling the Load method.

IgnoreOperation renamed to Ignore

IgnoreOperationAttribute has been renamed to IgnoreAttribute:

[IgnoreOpration] -> [Ignore]

DomainServiceDescriptionProvider and MetadataProvider combined into a single class

The DomainServiceDescriptionProvider class and the MetadataProvider class have been combined into the DomainServiceDescriptionProvider class. Anyone who has created a class that derives from DomainServiceDescriptionProvider or MetadataProvider will have to adapt the derived class for this change. As a result of this change, the following classes were also removed:

  • MetadataProviderAttribute
  • LinqToEntitiesTypeDescriptionProvider
  • LinqToSqlTypeDescriptionProvider

If you applied the LinqToEntitiesMetadataProvider or LinqToSqlMetadataProvider attribute, you must now use either the LinqToEntitiesDomainServiceDescriptionProvider or LinqToSqlDomainServiceDescriptionProvider attribute.

Load method on DomainContext now has strongly-typed callback parameter

Previously, one of the overloaded Load methods on the DomainContext accepted a parameter of type Delegate for the callback method. Now, that parameter is strongly-typed and accepts a parameter of the type Action<LoadOperation> or Action<LoadOperation<EntityType>>.

Invoke signatures changed on DomainClient and DomainService

In the previous release, the Invoke method contained distinct parameters for invoke operation arguments. Now, the Invoke methods accept a parameter object that contains those arguments. You create a new instance of the InvokeArgs class and pass it as a parameter when calling BeginInvoke or BeginInvokeCore on DomainClient. You create a new instance of the InvokeDescription class and pass it as a parameter when calling Invoke on the DomainService.

Removed EnableClientAccessAttribute.ServiceName property

The EnableClientAccessAttribute.ServiceName property has been removed. Instead, use the ServiceContractAttribute.Name property.

SubmitChanges on DomainDataSource no longer automatically reloads data

In the RC release, the DomainDataSource no longer automatically reloads the data when the SubmitChanges method successfully completes. You can reload the data after submitting changes by calling the Load method from an event handler for the SubmittedChanges event.

‘new’ keyword no longer permitted on entity properties

In the previous release, the new keyword was permitted on entity properties to allow polymorhphic property access in the server code. In the RC release, the new keyword is no longer permitted. An InvalidOperationException is raised if new is applied to an entity property.

Count<T>( ) method no longer automatically called by DomainService.Query( )

In the previous release, the Count<T> method was automatically called by the DomainService.Query method so the TotalEntitiesCount property on DomainClientResult could be set. In the RC release, the Count<T> method is no longer automatically called, and therefore the TotalEntitiesCount property is not set. This change was made to improve performance. To explicitly request that the Count method is called, you can set the IncludeTotalCount property on the EntityQuery to true.

Removal of DomainOperationEntry.IsAuthorized and addition of DomainService.IsAuthorized

The IsAuthorized method was moved from DomainOperationEntry to DomainService. The method signature was changed to:

public AuthorizationResult IsAuthorized(DomainOperationEntry domainOperationEntry, object entity)

The entity parameter can be null so a custom class that derives from AuthorizationAttribute must tolerate a null value for AuthorizationContext.Instance.

Generated code changed for domain services that derive from LinqToEntitiesDomainService

The code that is generated when you use the DomainService Wizard to create a domain service that exposes Entity Framework classes has changed. In the previous release, the generated code assumed a single entity set. In the RC release, you can set the correct entity set for an entity in your code. The AttachAsModified extension method was also changed so it no longer assumes an instance of EntityObject. There were no changes to the generated code for the default query method. The following table shows the previous code generation and the new code generation. If you created your domain service manually, you must make this changes in your code.

Changes to DomainDataSource

The DomainDataSource class includes several changes that were were made to leverage Silverlight 4 features - DependencyObject data binding and Commanding. The following changes were made for the RC release:

  1. DomainDataSource.SubmitChanges() No Longer Causes a Reload

The SubmitChanges method on DomainDataSource has been changed so that it will not automatically invoke a reload when it completes successfully. Equivalent behavior can be achieved by invoking the Load method from the SubmittedChanges event

  1. Descriptors changed to DependencyObjects

The FilterDescriptor, GroupDescriptor, Parameter, and SortDescriptor have been changed to DependencyObjects. This makes all their properties available for data binding. For instance, FilterDescriptor.Value can now be bound directly instead of requiring the use of a ControlParameter.

Was

   1: <dds:FilterDescriptor PropertyPath="MyProperty" Operator="IsEqualTo">
   2:   <dds:ControlParameter ControlName="textBox1" ParameterName="Text"
   3:       RefreshEventName="TextChanged" />
   4: </dds:FilterDescriptor>

Now

   1: <dds:FilterDescriptor PropertyPath="MyProperty" Operator="IsEqualTo"
   2:     Value="{Binding ElementName=textBox1, Path=Text}" />

FilterDescriptor.Value, GroupDescriptor.PropertyPath, and SortDescriptor.PropertyPath are no longer Parameter types. Instead each has been made an Object or String as appropriate. To access the properties in code, you now use descriptor.Value instead of descriptor.Value.Value.

Additionally, the FilterDescriptorCollection, GroupDescriptorCollection, ParameterCollection, and SortDescriptorCollection have all been made into DepedencyObjectCollections to facilitate the new binding behavior. This has rendered the following types obsolete, and they have been removed from the framework:

· ControlParameter

· ObservableItemCollection

· ItemChangedEventArgs

· ParameterTypeConverter

  1. FilterDescriptors made read-only

The FilterDescriptors property on DomainDataSource is now always initialized to a non-null value and is no longer settable.

Was

   1: <dds:DomainDataSource.FilterDescriptors>
   2:   <dds:FilterDescriptorCollection>
   3:     <dds:FilterDescriptor ...="" />
   4:     <dds:FilterDescriptor ...="" />
   5:   </dds:FilterDescriptorCollection>
   6: </dds:DomainDataSource.FilterDescriptors>
   7:  
   8:  
   9:  

Now

   1: <dds:DomainDataSource.FilterDescriptors>
   2:   <dds:FilterDescriptor ...="" />
   3:   <dds:FilterDescriptor ...="" />
   4: </dds:DomainDataSource.FilterDescriptors>
   5:  

LogicalOperator moved from FilterDescriptorCollection to DomainDataSource

The LogicalOperator property on the FilterDescriptorCollection has been relocated to the DomainDataSource. The property is now named FilterOperator.

Was

   1: <dds:DomainDataSource ...="">
   2:   <dds:DomainDataSource.FilterDescriptors>
   3:     <dds:FilterDescriptorCollection LogicalOperator="Or">
   4:       <dds:FilterDescriptor ...="" />
   5:     </dds:FilterDescriptorCollection>
   6:   </dds:DomainDataSource.FilterDescriptors>
   7: </dds:DomainDataSource>

Now

   1: <dds:DomainDataSource FilterOperator="Or" ...="">
   2:   <dds:DomainDataSource.FilterDescriptors>
   3:     <dds:FilterDescriptor ...="" />
   4:   </dds:DomainDataSource.FilterDescriptors>
   5: </dds:DomainDataSource>
  1. ModifiedFilterParameters and ModifiedQueryParameters removed

The ModifiedFilterParameters and ModifiedQueryParameters properties have been removed from LoadingDataEventArgs and LoadedDataEventArgs.

  1. FilterDescriptor.IgnoreValue default value changed to FilterDescriptor.DefaultIgnoredValue

The default behavior of the IgnoredValue property on the FilterDescriptor has changed to prevent unintended matching. Previously, the default IgnoredValue was an empty string. Now, it defaults to FilterDescriptor.DefaultIgnoredValue.

If you expect an empty string to be ignored by the filter, you are now required to explicitly set the IgnoredValue.

Was

   1: <dds:FilterDescriptor PropertyPath="MyProperty" Operator="IsEqualTo">
   2:   <dds:ControlParameter ControlName="textBox1" ParameterName="Text"
   3:       RefreshEventName="TextChanged" />
   4: </dds:FilterDescriptor>

Now

   1: <dds:FilterDescriptor PropertyPath="MyProperty" Operator="IsEqualTo"
   2:     IgnoredValue=""
   3:     Value="{Binding ElementName=textBox1, Path=Text}" />
   4:  
  1. Descriptor validation moved to DomainDataSource.Load

A majority of the validation for the FilterDescriptor, GroupDescriptor, Parameter, and SortDescriptor types has been moved to the Load method on the DomainDataSource. If a descriptor is not defined when the Load method is invoked, an error will be raised in the LoadedData event.

When the DomainDataSource is auto-loading, a few immediate validation checks are performed. The PropertyPaths must all be valid. Also, if FilterDescriptor.Value or Parameter.Value cannot be converted to the underlying property type, the auto-load will be postponed until the conversion is successful.

Freitag, 16. April 2010

Visual Studio 2010 Webcasts und Quick Hits Links

Oliver Scheer hat auf seiner Seite jede Menge nützlicher Links und Webcasts zum Themenkreis Visual Studio 2010 zusammengestellt: o-LIVE-r : Visual Studio 2010 Webcasts und Quick Hits Links

IDE Quick Hits

VS 2010 Quick Hit: Multi-Line Editing

VS 2010 Quick Hit: Intellisense

VS 2010 Quick Hit: Generate from Usage

VS 2010 Quick Hit: Multi-Targeting

VS 2010 Quick Hit: Navigate To

VS 2010 Quick Hit: Extension Manager

VS 2010 Quick Hit: Exportable Breakpoints

Webcasts

Überblick

Visual Studio 2010 & .NET Framework 4 - Highlights

Anwendungsentwicklung mit Visual Studio 2010

Application Development mit Visual Studio 2010 (Teil 1 von 5) - Agile Software Development mit VS 2010

Application Development mit Visual Studio 2010 (Teil 2 von 5) - Entwicklung einer Windows Forms Anwendung mit VS 2010

Application Development mit Visual Studio 2010 (Teil 3 von 5) - Testing der Windows Forms Anwendung mit VS 2010

Application Development mit Visual Studio 2010 (Teil 4 von 5) - Erweiterung der Anwendung mit dem ASP.NET MVC 2, WF 4 und EF 4 (Part 1)

Application Development mit Visual Studio 2010 (Teil 5 von 5) - Erweiterung der Anwendung mit dem ASP.NET MVC 2, WF 4 und EF 4 (Part 2)

IDE

Visual Studio 2010 - Die Entwicklungsumgebung

Sprachen

C# 4.0 - Neues im Überblick

Neue Features in Visual Basic 2010 - Intellisense, Interop & mehr?

VS 2010 und C++ - Was gibt es Neues?

Die Dynamic Language Runtime - Dynamische Sprachen auf .NET

IronPython im Überblick - Python-Programmierung auf dem Microsoft .NET Framework

Frameworks

Managed Extensibility Framework - Eine Einführung

Windows Workflow 4 - Die Neuerungen

Parallele Programmierung mit .NET 4.0 - Neue Methoden zur Multikern-Programmierung

Neuheiten in ASP.NET 4.0 - Teil 1 - Neue Funktionen in den ASP.NET-Kerndiensten und neue Serversteuerelemente

Neuheiten in ASP.NET 4.0 - Teil 2 - Clientseitige Datenbindung mit ASP.NET AJAX, Verbesserungen der Steuerelemente und neue Funktion der IDE

ASP.NET MVC 2 - Eine Einführung

ASP.NET AJAX - Microsoft AJAX und das .NET Framework 4.0

Ribbon- und Backstage-Programmierung mit Visual Studio 2010 und Office 2010 - User Interface Integration in Office 2010 mit C# 4.0

MFC mit Visual Studio 2010 - Der Ribbon-Designer

Entity Framework 4 - Was ist neu?

WCF Data Services 1.5 - Was ist neu?

Team Foundation Server (Basic Installation)

Team Foundation Server 2010 für Einsteiger und kleine Teams (Teil 1 von 2) - TFS 2010 auf Windows 7 installieren bis zum ersten Check-In

Team Foundation Server 2010 für Einsteiger und kleine Teams (Teil 2 von 2) - Team Build und Version Control Branches einfach gemacht

Donnerstag, 18. Februar 2010

SEO mit ASP.NET 3.0, Visual Studio 2008

Wie ja vielleicht viele wissen, wird es mit ASP.NET 4.0 und Visual Studio 2010 einige SEO-Erweiterungen geben. Nachzulesen zum Beispiel im MSDN Magazin im Artikel Search Engine Optimization with ASP.NET 4.0, Visual Studio 2010 and IIS7. Doch man muss nicht auf ASP.NET 4.0 warten, um seine Seiten für Suchmaschinen zu optimieren. Ich möchte hier nicht die üblichen statischen SEO Tipps - wie zum Beispiel Images mit Title und beschreibenden Alt-Tag bestücken, auf Keyword Density achten, usw. – beschreiben, sondern auf zwei effektive dynamische Methoden hinweisen.
Zum einem kann man durch URL Rewriting die normalerweisen kryptischen URL’s, wie z.B. show_album.aspx?ID=4711 zum Anzeigen eines speziellen Photoalbums, in die Suchmaschinen freundliche Schreibweise /Bilder_Lufthansa_Halbmarathon_Frankfurt ersetzen oder durch dynamisches Ergänzen der Metatags im Page_Load die entsprechenden Keywords in Abhängigkeit vom konkreten Inhalt versorgen.

SEO-Tip: URL-Rewriting

Für das URL-Rewriting gibt es normalerweise unzählige Tools, die einem das URL-Rewriting auf IIS-Ebene oder durch Erweiterungen wie URL Mapping (Tip/Trick: Url Rewriting with ASP.NET - ScottGu's Blog) ermöglichen. Doch es gibt auch einen sehr pragmatischen Ansatz, wenn man sich wieder auf die etwas verstaubte global.asax besinnt.
Hier kann man im Application_BeginRequest auf folgende Art und Weise prüfen, ob es sich bei der aktuellen URL, um eine optimierte URL (z.B. bilder_Lufthansa_halbmarathon) handelt. Dann aus dem extrahierten Titel die ID des Fotoalbums ermitteln und dann die eigentliche URL (z.B. PhotoAlbum_Contents_s.aspx?Albumid=4711) zusammenbauen. Durch die RewritePath-Methode wird dann der Request auf diese URL umgebogen.
void Application_BeginRequest(Object sender, EventArgs e)
{
string originalPath = HttpContext.Current.Request.Path.ToLower();
Regex rewrite_regexBilder = new Regex(@"bilder_((.+)\.aspx)", RegexOptions.IgnoreCase);
try
{
//see if we need to rewrite the URL
Match match_rewrite = rewrite_regexBilder.Match(originalPath);
if (match_rewrite.Success)
{
string[] cap1 = match_rewrite.Groups[0].Captures[0].ToString().Split('/');
string titleComp = "";
if (cap1.Length > 0)
titleComp = cap1[cap1.Length - 1];
else
titleComp = match_rewrite.Groups[0].Captures[0].ToString();
// Bilder_ abschneiden und .aspx abtrennen
string title = titleComp.Substring(7, titleComp.Length - 12).Replace("_", " ");
int albumid = lnAppFactory_P.getAlbumIDByTitle(title);
if (albumid != 0)
{
string newURL = originalPath.Replace(titleComp, "PhotoAlbum_Contents_s.aspx?Albumid=" + albumid.ToString());
Context.RewritePath(newURL, true);
}
}


SEO-Tip: Metatags dynamisch ergänzen

Um eine dynamische Seite mit den Keywords vom konkreten Inhalt zu füllen, kann man diese Keywords zunächst ermitteln. Dies kann man zum Beispiel dadurch lösen, das man in der Datenbanktabelle noch eine Zusatzspalte Keywords anlegt und diese dann über die entsprechende ID im Page_Load-Event ausliest. Danach muss man im Page-Load-Event nur noch die Metatags neu setzen:


HtmlMeta description = new HtmlMeta();
HtmlMeta keywords = new HtmlMeta();
Page.Title = sTitle;
keywords.Name = "Keywords";
description.Name = "Description";
description.Content = sDescription;
keywords.Content = sKeywords;
Page.Header.Controls.Add(keywords);
Page.Header.Controls.Add(description);