Microsoft SQL Server: Führende Nullen bei alphanumerischem String abschneiden

Problem

Ein String (z.B. eine Materialnummer oder eine Artikelnummer) besteht aus alphanumerischen Zeichen (z.B. 00003j422a3) und hat führende Nullen, welche abgeschnitten werden sollen (Ergebnis: 3j422a3). Siehe auch „Führende Nullen bei numerischen Strings abschneiden“.

Ansatz

* Zuerst werden ALLE Nullen durch Leerzeichen ersetzt
* danach werden alle Leerzeichen auf der linken Seite mit LTRIM abgeschnitten
* anschließend werden alle Leerzeichen durch 0en ersetzt.

Prämissen / Vorraussetzungen

Es sind keine Leerzeichen in dem String

Lösung

SELECT REPLACE(LTRIM(REPLACE(artikelnummer, '0', ' ')), ' ', '0') FROM dbo.cube1

Adobe Flex 3: Drag and Drop API

Aufgabenstellung

UI-Komponenten sollen per Drag and Drop verschoben werden können.

Ansatz

Dieser Artikel beschreibt die notwendigen Flex-APIs (DragManager) für die Implementierung einer Drag and Drop-Funktionalität am Beispiel der (siehe Nachfolgeartikel) eLearning-Anwendung für das V-Modell.

Lösung

1.) Definition der verschiebbaren Komponenten und der Behälter-Komponenten.

<!-- WIRD VERSCHOBEN -->
<mx:Button dragComplete="dragCompleteHandler(event);" 
label="System-Entwurf" id="btnSystementwurf"  />
<mx:Button dragComplete="dragCompleteHandler(event);" 
label="Software-Entwurf" id="btnSoftwareentwurf"  />
..

<!-- WIRD HINEINGESCHOBEN -->
<mx:HBox verticalAlign="middle" verticalScrollPolicy="off" 
horizontalScrollPolicy="off" id="dropField1" />
<mx:HBox verticalAlign="middle" verticalScrollPolicy="off" 
horizontalScrollPolicy="off" id="dropField2" />

2.) Registrierung der Eventlistener


<mx:Application creationComplete="{onCreationComplete()} ...

public function onCreationComplete():void
{
   // Registrierung des Buttons "Anforderungsanalyse" für das Verschieben in ein Feld
   this.btnAnforderungsnanalyse.addEventListener( MouseEvent.MOUSE_DOWN, beginDrag );

   // Registrierung des Buttons "AbnahmeEntwurf" für das Verschieben in ein Feld
   this.btnAbnahmeEntwurf.addEventListener( MouseEvent.MOUSE_DOWN, beginDrag );

...

   // Die DropListener werden an die UI-Komponten, bzw. die Komponeten, in die 
   // die Objekte geschoben werden können, angehängt
   this.dropField1.addEventListener( DragEvent.DRAG_ENTER, acceptDrop );
   this.dropField2.addEventListener( DragEvent.DRAG_ENTER, acceptDrop );
   ..
   this.dropField1.addEventListener( DragEvent.DRAG_DROP, handleDrop );
   this.dropField2.addEventListener( DragEvent.DRAG_DROP, handleDrop );
}
&#91;/actionscript3&#93;

3.) Implementierung der Logik - Hier: Überprüfung ob alles richtig verschoben ist
&#91;actionscript3&#93;
private function dragCompleteHandler(event:DragEvent):void {
     var draggedButton:Button = event.dragInitiator as Button;
     var dragInitCanvas:HBox = event.dragInitiator.parent as HBox;

     var stimmt1:Boolean = getButtons(dropField1).indexOf('btnAnforderungsnanalyse')>-1;
     var stimmt2:Boolean = getButtons(dropField2).indexOf('btnSystemarchitektur')>-1;
               	
     if(stimmt1&&stimmt2) 
     {
          Alert.show('Congratulations you did it!'); 
     }                	 
}  

4.) Welche Buttons sind in den Container? (Hier HBOX)

private function getButtons(box:HBox):String
{
var btnString:String=“;
var numChildren:Number = box.numChildren;

for (var i:int = 0; i < numChildren; i++) { if(box.getChildAt(i)["id"]) { btnString=box.getChildAt(i)["id"]; } } return btnString; } [/actionscript3] 5.) Management der Drag and Drop Funktionalität [actionscript3] public function beginDrag( mouseEvent:MouseEvent ):void { // the drag initiator is the object being dragged (target of the mouse event) var dragInitiator:IUIComponent = mouseEvent.currentTarget as IUIComponent; // the drag source contains data about what's being dragged var dragSource:DragSource = new DragSource(); // add some information to the drag source dragSource.addData( "name", dragInitiator.name ); dragSource.addData( "parent", dragInitiator.parent.name ); // ask the DragManger to begin the drag DragManager.doDrag( dragInitiator, dragSource, mouseEvent, null ); } public function handleDrop( dragEvent:DragEvent ):void { var dragInitiator:Button = Button( dragEvent.dragInitiator ); var dropTarget:HBox = dragEvent.currentTarget as HBox; HBox(dropTarget).addChild(dragInitiator); } public function acceptDrop( dragEvent:DragEvent ):void { var dropTarget:IUIComponent = dragEvent.currentTarget as IUIComponent; var dragSource:DragSource = dragEvent.dragSource; // accept the drop DragManager.acceptDragDrop( dropTarget ); // show feedback DragManager.showFeedback( DragManager.MOVE ); } [/actionscript3]

OLE DB Zugriff: C# auf MDB (Microsoft Access Datenbank) mit JET Treiber

Selektionsanweisung mit Parametern

public ArrayList getWeekPlan(string kapno, string woche)
{
   ArrayList weekPlan = new ArrayList();

   OleDbConnection conn = new OleDbConnection(
   "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\\\\pfad1\\db.mdb");

   try
   {

      conn.Open();
      OleDbCommand comm = new OleDbCommand();
      comm.Connection = conn;
      comm.CommandText = "SELECT [Datum],[KapazitätNo] "+
      "FROM [qry_TagesAnsichtMengen] WHERE [KapazitätNo]=@kapno "+
      "AND [DINKW]=@woche";

      comm.Parameters.AddWithValue("kapno", kapno);
      comm.Parameters.AddWithValue("woche", woche);
      
      OleDbDataReader reader = comm.ExecuteReader();
      
       while (reader.Read())
       {
          WeekPlanVO vo = new WeekPlanVO();
          vo.datum = reader.GetValue(0).ToString();
          vo.menge = reader.GetValue(1).ToString();
          weekPlan.Add(vo);
        }
   }
   catch (Exception e)
   {
     WeekPlanVO vo = new WeekPlanVO();
     vo.datum = e.Message;
     vo.menge = e.Message;
     weekPlan.Add(vo);
     return weekPlan;
   }
   finally
   {
      conn.Close();
   }
  return weekPlan;
}

Manipulationsanweisung ohne Parameter

public string updateDetailDate(DateTime neuesDatum, DateTime altesDatum, 
string neueKW, string alteKW, string kapazitaet, string material, string beleg)
{
  OleDbConnection conn = new OleDbConnection(
  "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\\\\pfad1\\db.mdb");

  
  try
  {
     conn.Open();
     OleDbCommand comm = new OleDbCommand();
     comm.Connection = conn;
     comm.CommandText = "UPDATE qry_Details_Akt SET [changed]=Now(), DinkW=" + neueKW + 
      ", WEWA_C='" + DateWrapper.GetServerDate(neuesDatum) + "', WEWA_C_OLD='" +
     DateWrapper.GetServerDate(altesDatum) + "' WHERE Beleg='" + beleg + 
     "'AND DinkW=" + alteKW + " AND Material='" + material + "' AND KapazitätNo=" + 
     kapazitaet;

     comm.ExecuteNonQuery();
  }
  catch (Exception e)
  {
      return e.Message+' '+e.StackTrace;
  }
  finally
  {
      conn.Close();
  }

  return "ok";
}

Flex 3: Bemalbares mx:Canvas mit FluorineFX-Messaging (Montagsmaler)

Aufgabenstellung

Unter Verwendung der FluorineFX Messaging-API soll eine Montagsmaler-Anwendung implementiert werden. Dies bedeutet dass ein User auf eine Leinwand zeichnet und die anderen Seitenbesucher in Echtzeit eine Aktualisierung auf dem Bildschirm erhalten. Dies kann auch als Grundlage für weitere Kollaborationsanwendungen genutzt werden, in denen man gemeinsam ein Dokument konstruieren möchte.

Ansatz

Nachdem die Zeichnenfunktionalität implementiert ist, werden die Bildpunkte beim loslassen der Maustaste (MOUSE_RELEASE_EVENT) an alle Clients übertragen. Die Clients reagieren bei einer einkommenden Menge an Bildpunkten und zeichnen sofort auf die Leinwand. Es wird immer die komplette Leinwand mit allen Bildpunkten beim Mouse-Release gesendet.

Durch das Publisher/Subscriber-Prinzip abonniert die Flex-Anwendung beim Start sofort die Datenquelle „painter„. Die Datenquelle erhält Bildpunkte und verteilt sie an alle Abonennten, wenn diese nach dem zeichnen die Maus gesehn lassen.

Vorraussetzungen

Die FluorineFX-Konfigurationsdatei wird angepasst, so das es eine neue Messaging Quelle „painter“ existiert.

Konfiguration des Backends

services-config.xml:

<?xml version="1.0" encoding="utf-8" ?> 
<services-config>
    <services>
        <service-include file-path="remoting-config.xml" />
        <service-include file-path="messaging-config.xml" />
    </services>
    
    <!-- Custom authentication -->
    <security>
    </security>
    
    <channels>
        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
           <endpoint uri="http://{server.name}:{server.port}/{context.root}/Gateway.aspx" 
             class="flex.messaging.endpoints.AMFEndpoint"/> 
            <properties>
            </properties>
        </channel-definition>

        <channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
            <endpoint uri="rtmp://{server.name}:2037" 
            class="flex.messaging.endpoints.RTMPEndpoint"/>
            <properties>
                <idle-timeout-minutes>20</idle-timeout-minutes>
            </properties>
        </channel-definition>

    </channels>
</services-config>

messaging-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<service id="message-service" class="flex.messaging.services.MessageService" 
    messageTypes="flex.messaging.messages.AsyncMessage">

     <!-- DO NOT CHANGE <adapters> SECTION-->
    <adapters>
	<adapter-definition id="messagingAdapter" 
             class="FluorineFx.Messaging.Services.Messaging.MessagingAdapter" 
             default="true"/>
    </adapters>
    <destination id="chat">
	<adapter ref="messagingAdapter"/>
        <properties>
            <network>
                <session-timeout>0</session-timeout>
            </network>
        </properties>
        <channels>
            <channel ref="my-rtmp"/>
        </channels>
    </destination>
    <destination id="textchat">
	<adapter ref="messagingAdapter"/>
        <properties>
            <network>
                <session-timeout>0</session-timeout>
            </network>
        </properties>
        <channels>
            <channel ref="my-rtmp"/>
        </channels>
    </destination>
    <destination id="painter">
	<adapter ref="messagingAdapter"/>
        <properties>
            <network>
                <session-timeout>0</session-timeout>
            </network>
        </properties>
        <channels>
            <channel ref="my-rtmp"/>
        </channels>
    </destination>
    <destination id="opminboxrefresher">
	<adapter ref="messagingAdapter"/>
    	<properties>
	    <network>
            	<session-timeout>0</session-timeout>
            </network>
    	</properties>
    	<channels>
         	<channel ref="my-rtmp"/>
    	</channels>
    </destination> 
</service>

Konfiguration des Frontends

Bei den Frontend Konfigurationsdateien kann einfach die Datei services-config.xml und die Datei messaging-config.xml kopiert werden. Es können aber absolute Pfade anstelle der Platzhalter wie {server.name},{server.port},{context.root} genutzt werden. Hierdurch ist eine lokale Entwicklung der Flex-Anwendungen mit einem entfernten IIS Server möglich.

Lösung

PaintMessaging.mxml (Projektdatei)

<?xml version="1.0" encoding="utf-8"?>
<mx:Application creationComplete="{init()}" xmlns:mx="http://www.adobe.com/2006/mxml" 
	layout="absolute" xmlns:components="components.*">
	<mx:Script>
		<!&#91;CDATA&#91;
			import models.ModelLocator;
			import mx.controls.Alert;
			import mx.messaging.events.MessageFaultEvent;
			import mx.messaging.events.MessageEvent;
			import mx.messaging.messages.AsyncMessage;
			import mx.managers.CursorManager;
			&#91;Bindable&#93;
            &#91;Embed(source="../assets/stiftklein.png")&#93;
            private var stift:Class;
            
            public var cursorID:int;
            
            public function init():void 
            {
            	consumer.subscribe();
            }
            
            public function mouseOverHandler(event:MouseEvent):void
            {
            	
            }
            
            public function downEvent(event:MouseEvent):void 
            {
            	
            } 
            
            public function upEvent(event:MouseEvent):void
            {
            	
            }
            
	private function messageHandler(event:MessageEvent):void
    	{
    	    ModelLocator.getInstance().lines=event.message.body as Array;
    	    dc_main.invalidateDisplayList();
    	}
   
   	private function messagefaultHandler(event:MessageFaultEvent):void
   	{ 
   	   Alert.show(event.faultCode+' '+event.faultDetail+' '+event.faultString); 
   	}     		
            
	&#93;&#93;>
	</mx:Script>
	<mx:Consumer id="consumer" destination="painter" 
		message="messageHandler(event)" fault="messagefaultHandler(event)"/>
    <mx:Producer id="producer" destination="painter" 
    	fault="messagefaultHandler(event)"/>		

    <mx:Panel mouseOver="{ cursorID = CursorManager.setCursor(stift); }" 
    	mouseOut="{CursorManager.removeCursor(cursorID);}" 
    	layout="absolute" 
    	title="Montagsmaler by Björn Karpenstein" 
    	backgroundColor="#ffffff" 
    	borderThicknessBottom="10" left="20" 
    	right="20" top="20" bottom="20">
       <components:DrawableCanvas id="dc_main" backgroundColor="#ffff80" 
       	backgroundAlpha="0" width="100%" height="100%" y="0" x="0">
       </components:DrawableCanvas>
    </mx:Panel>
		
</mx:Application>

DrawableCanvas.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" 
       creationComplete="init()">
    
    <mx:Script>
        <!&#91;CDATA&#91;
            
            public var lineWidth:Number = 5;
            
            public var lineColour:uint = 1;
            
            public var lineAlpha:Number = 1;
            
            
            private var enabler:DrawingEnabler;
            
            private function init():void
            {
                enabler = new DrawingEnabler(this);
            }            
            
            protected override function updateDisplayList(unscaledWidth:Number,
                            unscaledHeight:Number):void
            {
                super.updateDisplayList(unscaledWidth, unscaledHeight);
            
                if( enabler != null ) enabler.drawLines(graphics, lineWidth, 
                lineColour, lineAlpha);
            }
        &#93;&#93;>
    </mx:Script>
</mx:Canvas>

DrawingEnabler.as

package components
{
import flash.display.Graphics;
import flash.events.MouseEvent;

import models.ModelLocator;

import mx.core.Application;
import mx.core.UIComponent;
import mx.messaging.messages.AsyncMessage;

public class DrawingEnabler
{
private var _target:UIComponent;

private var _curentLine:Array;

public function DrawingEnabler( target:UIComponent ):void
{
_target = target;
_target.addEventListener(MouseEvent.MOUSE_DOWN, downEvent);
_target.addEventListener(MouseEvent.MOUSE_UP, upEvent);
_target.addEventListener(MouseEvent.MOUSE_OUT, upEvent);
}

public function sendMessage(stream:Array):void
{
var message:AsyncMessage = new AsyncMessage();
message.body = stream;
Application.application.producer.send(message);
}

public function newLine():void
{
_curentLine = new Array();
ModelLocator.getInstance().lines.push( _curentLine );

if( ModelLocator.getInstance().lines.length > 10 )
ModelLocator.getInstance().lines.shift();
}

public function addPoint(xIN:int, yIN:int):void
{
_curentLine.push( { x:xIN, y:yIN } );
_target.invalidateDisplayList();
}

public function drawLines(graphics:Graphics,lw:Number,lc:uint,la:Number):void
{
graphics.clear();
graphics.lineStyle(lw,lc,la);

for( var j:int = 0; j

Flex 3 und Google Maps API

Aufgabenstellung

In eine Flex-Anwendung soll Google Maps integriert werden.

Ansatz

1.) Aufruf der Seite http://code.google.com/intl/de/apis/maps/documentation/flash/
2.) Runterladen der Flash-Bibliothek (SWC-Datei) und einfügen in das LIBS-Verzeichnis der Flex-Anwendung
3.) Anfordern des Schlüssels unter „Wie beginne ich…“ und eintragen in den Code unten.

Lösung

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
	<!&#91;CDATA&#91;
		import com.google.maps.overlays.Marker;
		import com.google.maps.controls.ZoomControl;
		import com.google.maps.geom.Attitude;
		import mx.controls.Alert;
		import com.google.maps.*;
		import com.google.maps.geom.*;
		import com.google.maps.services.GeocodingEvent;
		import com.google.maps.services.ClientGeocoder;
		import com.google.maps.controls.NavigationControl;
		import com.google.maps.controls.MapTypeControl;
		import com.google.maps.MapEvent;
		
		public function onMapReady(event:MapEvent):void
		{
			// Die Bedienelemente der Karte hinzufügen
			map.addControl(new MapTypeControl());
			map.addControl(new NavigationControl());
			this.geocodeLocation('Fulda, Am Rinnweg 15');
		}
		
		public function onMapPreinitialize(event:MapEvent):void
		{
			var myMapOptions:MapOptions = new MapOptions();
			myMapOptions.viewMode = View.VIEWMODE_2D;
			myMapOptions.mapType=MapType.NORMAL_MAP_TYPE;
			//myMapOptions.zoom=0;
			map.setInitOptions(myMapOptions);
		}
		
		private function geocodeLocation(location:String=''):void
		{
			var geocoder:ClientGeocoder = new ClientGeocoder();
			geocoder.addEventListener(GeocodingEvent.GEOCODING_SUCCESS,
			geoCodeSuccess);
			geocoder.addEventListener(GeocodingEvent.GEOCODING_FAILURE, 
			geoCodeFailure);

			if(location!='')
			{
				geocoder.geocode(location);
			}
			else
			{
				geocoder.geocode(search.text);
			}
		}
		
		private function geoCodeSuccess(event:GeocodingEvent):void
		{
			var placemarks:Array = event.response.placemarks;
			map.flyTo(placemarks&#91;0&#93;.point, 18, new Attitude(35,60,35), 
			3);
			var marker:Marker = new Marker(placemarks&#91;0&#93;.point); 
			map.addOverlay(marker); 
		}
		
		private function geoCodeFailure(event:GeocodingEvent):void
		{
			Alert.show('Also wissense, das find ich einfach ned....',
                                       'Ähm...');			
		}		
	&#93;&#93;>
</mx:Script>
	<mx:TitleWindow layout="vertical" width="100%" height="100%" 
              title="Finde versteckte Schätze... 
             (c) die 1st-level-caches Schludi&amp;Mephi ">
		<maps:Map3D xmlns:maps="com.google.maps.*" 
			  id="map" 
			  mapevent_mapready="onMapReady(event)" 
			  mapevent_mappreinitialize="onMapPreinitialize(event)"
			  width="100%" 
			  height="100%"
    		  key="HIER KOMMT DER BEANTRAGTE GOOGLE KEY REIN"/>
    	<mx:HBox horizontalAlign="center" width="100%" height="30">
			<mx:Label x="70" y="524" text="Da will ich hin:" 
                                        width="120" fontWeight="bold"/>
			<mx:Button x="421" y="520" label="Suchen ..." 
                                        click="{geocodeLocation()}"/>
			<mx:TextInput id="search" x="167" y="520" 
                                       width="246"/>
    	</mx:HBox>
	</mx:TitleWindow>
</mx:Application>

Beispiel

http://baugebiete.fulda.de

FluorineFX: Standard Authentifizierung über die Session

Aufgabenstellung

Im Internet sollen sich Benutzer an einer Anmeldemaske einer Flex-Anwendung anmelden. Die Berechtigungen sollen anhand des Benutzernamens festgelegt werden.

Ansatz

1.) FLEX: Erstellen der Anmeldemaske mit User/Passwort
2.) C#: Überprüfung ob die User/Passwort-Kombination in der Datenbank vorhanden ist
3.) C#: Falls JA: Benutzer in die sessionvariable USERNAME schreiben / Falls NEIN: Tue nichts
4.) C#: Überprüfung der Backend-Services: Ist USERNAME leer?
NEIN: Darf der User die Daten aufrufen?? (Dem Benutzer kann eine ROLLE zugewiesen sein, siehe Artikel „FluorineFX: Windows Authentifierung… Single Sign On“, und anhand der Rolle kann ermittelt werden ob sie berechtigt ist die Daten abzurufen).
JA: Keine Daten ausliefern!!!
5.) FLEX: Falls user authentifziert: Maskenaufbau in der Flexanwendung entsprechend Rolle

Lösung

Hier die wichtigsten Auszüge aus meiner Lösung:

FLEX:

...
<mx:Script>
public function getAuthenticationHandler(event:ResultEvent):void
{
   if( (event.result as Boolean) )
   {
     // Schalte ViewStack um (keine Loginmaske mehr)
     loginStack.selectedChild=tarzanScreen;

     // Speichere Username in Modellocator (evtl. auch Rolle holen)
     ModelLocator.getInstance().myUser=txtUsername.text;
   }
   else
   {
      Alert.show('Wrong username or password!');
    }						
}
</mx:Script>
...
<mx:TextInput id="txtUsername" />
<mx:TextInput id="txtPasswort" displayAsPassword="true"/>
...
<mx:RemoteObject id="authenticationService" destination="GenericDestination"  
                                          source="TarzanServices.AuthenticationService" 
                                          showBusyCursor="true" 
                                          fault="faultHandler(event)" >
    <mx:method name="getAuthentication" result="getAuthenticationHandler(event)"/>
</mx:RemoteObject>

C#: Benutzername ermitteln: Falls „none“ einfach nix in Maske/Service machen:

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Data.SqlClient;
using System.Web;
using FluorineFx;
using System.Security.Principal;
...
public string getSessionUser()
{
    if (FluorineFx.Context.FluorineContext.Current.Session["username"]==null) 
    return "none";

    return FluorineFx.Context.FluorineContext.Current.Session["username"].ToString();
}

C#: Überprüfe ob User/Kennwort-Kombination in der Datenbank vorhanden ist, falls JA, schreibe USERNAME in Sesseion und liefere TRUE zurück, damit Flex weiß das es von der Login-Maske weg darf.. (REAKTION IN FLEX).

public bool getAuthentication(string username, string password)
{
   SqlConnection conn = new SqlConnection(MyConfigurationManager.msSqlServerString);

   try
   {
      conn.Open();
      SqlCommand comm = new SqlCommand();
      comm.Connection = conn;
      comm.CommandText = "SELECT * FROM [users] WHERE [username]=@username "+
                                     "AND [password]=@passwort";
      comm.Parameters.AddWithValue("username", username);
      comm.Parameters.AddWithValue("passwort", password);

      int i = 0;
      SqlDataReader reader = comm.ExecuteReader();

       while (reader.Read())
       {
              i++;
       }

       if (i > 0)
       {
           // Schreibe USER in die Datenbank
           FluorineFx.Context.FluorineContext.
           Current.Session["username"] = username;
       }

       return i > 0;
   }
   catch (Exception e)
   {
        return false;
   }

   return false;
}

FluorineFX: Single-Sign-On per Windows Authentifizierung

Aufgabenstellung

In einem Windows Netzwerk mit Windows Servern sollen beim Aufruf einer Intranet-Web-Anwendung der angemeldete Benutzer automatisch ermittelt werden, so dass keine Benutzername/Kennwort-Maske zusätzlich erforderlich ist. Anhand des Benutzernamens können Berechtigungen festgemacht werden, die z.B. über ein Benutzerrollen-Konzept zugewiesen werden können.

Ansatz

Es wird die FluorineFX-API verwendet um den Windows User zu ermitteln. Dies kann im Preloader der Flex/Flash-Anwendung geschehen. Die Masken werden nachträglich anhand der Rolle aufgebaut bzw. angepasst.

Definition des Benutzerrollenkonzeptes

Eine Rolle ist eine Aufgabe, die eine Person in einem Unternehmen hat. In der Datenbank würde man auf relationaler Ebene 3 Tabellen benötigen, um ein Benutzerrollen-Konzept zu realisieren. Ein Benutzer hat keine, eine oder mehrere Rollen, wobei eine Rolle keinem, einem oder mehreren Benutzern zugewiesen werden kann. Man benötigt also eine Tabelle USER und eine Tabelle ROLE. Da es sich hierbei um eine M:N-Beziehung handelt, ensteht eine Zusatztabelle USERROLE, die die Foreign Keys der Tabelle USER und ROLE speichert.

Vorraussetzungen

In der Firma wird vorzugsweise der Internet-Explorer verwendet. Die Verwendung von Firefox ist möglich, benötigt aber eine Spezialkonfiguration für Windows-Authentifizierung.

Im IE:

Unter Extras / Internetoptionen / Erweitert / Integrierte Windows Authentifzierung aktivieren

Im Firefox:

  • in der Adressleiste „about:config“ eingeben
  • im Fenster rechte Maustaste, dann Neu -> String
  • Eigenschaftsnamen „network.automatic-ntlm-auth.trusted-uris“ eingeben
  • String-Wert: Name des Portalrechners. Wenn auf das Portal beispielsweise

über http://musterfirma/teamworks zugegriffen wird ist der korrekte Wert „musterfirma“ eingetragen

Im IIS Manager sollte mit der rechten Maustaste auf der Web-Anwendung / Eigenschaften der Haken „Windows Authentication“ gesetzt sein, sonst liefert der IIS nichts zurück.

Lösung

1.) Anlegen der 3 Tabellen USER, USERROLE und ROLE.
2.) Der Windows-User kann in einem ordinären Backendservice mit folgendem Code ermittelt werden:

System.Security.Principal.WindowsPrincipal p =
System.Threading.Thread.CurrentPrincipal as System.Security.Principal.WindowsPrincipal;
string strName = p.Identity.Name;
string userWithDeletedDomainPrefix = strName.Substring(strName.IndexOf("\\") + 1).Trim();

3.) Reaktion in der Flex-Anwendung auf die zugewiesenen Rollen (Maskenaufbau)
4.) Schützen der Backendservices anhand der zugewiesenen Rollen (Auch ohne Flex keine sicherheitskritischen Daten aufrufbar)

ASP.NET und C#: Excel Dateien im Web darstellen

Aufgabenstellung

Eine Excel Datei, die in einer Firma ständig aktualisiert wird, soll auf Smart Phones (Blackberrys, iPhones, Windows Mobiles, HTCs …) abrufbar sein.

Vorraussetzungen

Vorweg solllte der Artikel „WebDAV mit IIS einrichten“ durchgearbeitet werden, um Zugriff zu bekommen.

Ansatz

Die Datei wird ortstransparent auf einem WebDAV-Laufwerk (siehe Artikel WebDAV einrichten) eines Microsoft IIS Server gespeichert, der nach dem Verfahren von Artikel „WebDAV einrichten“ konfiguriert ist.. Der Microsoft JET Treiber verfügt über die Fähigkeiten, Excel Dateien zu laden (nur XLS, nicht XLSX oder XLSM). Im IIS Server wird eine ASP.NET Anwendung angelegt. Das nachfolgende Beispiel ist so eingerichtet, das es versuchen wird aus dem Web Root der Anwendung eine Datei test.xls zu laden.

Lösung

Anlegen eine ASP.NET Seite:

<%@ Page Language="C#" AutoEventWireup="true"  
CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Unbenannte Seite</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="GridView1" runat="server">
        </asp:GridView>
        &nbsp;</div>
        <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
    </form>
</body>
</html>

… mit dem folgenden Code:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.OleDb;

public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {

        string appPath = HttpContext.Current.Request.ApplicationPath;
        string physicalPath = HttpContext.Current.Request.MapPath(appPath).
                                                         Replace("\\","\\\\");

        string ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; 
        Data Source="+physicalPath+"\\test.xls; Extended Properties="+
                                                              \"Excel 8.0;HDR=Yes\";";

        string CommandText = "select * from [Tabelle1$]";

        OleDbConnection myConnection = new OleDbConnection(ConnectionString);
        OleDbCommand myCommand = new OleDbCommand(CommandText, myConnection);

        myConnection.Open();

        GridView1.DataSource = myCommand.ExecuteReader(CommandBehavior.CloseConnection);
        GridView1.DataBind();

        myConnection.Close();

        Label1.Text = physicalPath;
    }
}

Beispiel

Diese Datei kann per WebDAV bearbeitet werden:
http://178.77.69.22/test.xls

und wird on-the-fly in eine HTML-Seite umgewandelt:
http://178.77.69.22/exceltoweb/Default.aspx

Wie aktuell ist noch HTML 5?

HTML 5 ist nicht gleich HTML 5

HTML 5 entstand nicht durch das W3C-Konsortium, sondern war ursprünglich eine Spezifikation von WHATWG, einer Arbeitsgruppe von großen Browserherstellern. Nach einiger Zeit wurde das W3C darauf aufmerksam, wollte sich allerdings nicht der WHATWG anschließen und entwickelte an einer Kopie der Spezifikation weiter. Seitdem gibt es 2 unterschiedliche Versionen oder Auffassungen, die ein gemeinheitliches Verständnis von HTML 5 verhindern. Nach dem Verständnis von WHATWG, soll vom jetzigen Standpunkt eine rollierende, iterative Entwicklung stattfinden, so dass es kein HTML 6 geben wird… das W3C hingegen beruft sich auf Spezifikationsstände, die in einer Versionsnummer kenntlich gemacht werden sollen (wie bisher).

Wenn wir als Web-Entwickler von HTML 5 sprechen, müssen wir immer klar machen, auf welche Spezifikation wir uns beziehen und vor allem: ZU WELCHEM ZEITPUNKT. Momentan gibt es kein einheitliches Verständnis von HTML 5 und die meisten Internetnutzer fragen sich, über welche sinnlosen Dinge wir uns den Kopf zerbrechen, denn ihr Webbrowser „kann doch schon HTML 5″….

Browserunterstützung – Stand: 6. Januar 2011

Auf der Seite http://html5test.com/ lässt sich die Browserkompatibilität mit HTML 5-Seiten testen. Welcher Spezifikation das genügt, müsste man im Detail untersuchen.

  • Internet Explorer 7 ist das Schlusslicht: 21 von 300 Punkten
  • Internet Explorer 9 PPT hat bereits 79 von 300 Punkten
  • der aktuelle Firefox 3.6.13 erhält 139 von 300 Punkten
  • die Beta Version vom 4er Firefox erhält bereits 235 von 300
  • Opera 10.62 bekommt 203 von 300 Punkten
  • Apple Safari 5.0.1 erhält 178 von 300 Punkten
  • Gewinner ist Google Chrome / Chromium 7 mit 262 von 300 möglichen Punkten.

Bei dem beachtlichen Marktanteil vom Internet Explorer (immerhin über 50 Prozent) spielt es keine Rolle welcher Browser der bessere HTML 5 Interpreter ist … Internetseiten sollen barrierefrei und browserunabhängig für jeden Nutzer lesbar bleiben…

Wer unbedingt jetzt schon HTML5 nutzen will…

… kann das HTML 5 Boilerplate einsetzen. Hierbei handelt es sich um einige Bibliotheken, die nach der Einbindung bei älteren Browsern eine Ersetzung von HTML5-Tags in Browser-verständliche Elemente vornimmt. Die funktioniert in einigen Browsern wie dem Firefox aber nur bedingt…

Mein Fazit…

… ist, wenn sich die Herrschaften mal geeinigt haben, was HTML 5 ist, wird das mit Sicherheit eine tolle Sache. Bis dahin sollte man darauf verzichten. Die gerühmten Elemente wie WebGL, die das Erstellen von 3D-Objekten im Browser ermöglichen, sind eigentlich kein Bestandteil der Spezifikation, werden aber mit HTML 5 in Verbindung gebracht.

by Björn Karpenstein