Archiv für den Monat August 2014

FileUpload mit AngularJS und ASP.NET MVC mit HttpPostedFileBase


Leider gibt es in AngularJS keine nativ integrierte Direktive für den Upload von Dateien. Es existieren aber diverse Möglichkeiten auch mit AngularJS Dateien hochzuladen. Zum einen gibt es zahlreiche fertige Upload Direktiven von Community Mitgliedern

Wenn man nur einen simplen Upload von Dateien umsetzen möchte, kann man das ganze auch recht schnell selbst schreiben. Dazu gibt es ebenfalls genug Hilfe im Netz und ich habe mich im Großen und Ganzen an die folgende Anleitung gehalten:

http://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs

Das ganze dann mit ASP.NET MVC im Backend kann folgendermaßen aussehen.

Als erstes benötigen wir eine Funktion im Controller die unsere Datei entgegennimmt. Ich sende außerdem mit den Dateien noch ein Personen Objekt mit. Hier ist es mit leider nicht gelungen, das Personen Objekt vom MVC Modelbinder entsprechend erkannt und gefüllt wird. Als die Upload Funktion noch die Struktur

“public JsonResult Upload(HttpPostedFileBase file, UploadPerson person)” hatte,

war “person” immer null, hier freue ich mich gerne über einen entsprechenden Hinweis wie man das lösen kann, denn ich habe hier spontan keine Lösung gefunden. Daher parse ich das Person Objekt aktuell per “Hand” über den JavaScriptSearializer, denn in den Formdaten werden die Daten entsprechend mit übergeben.

[HttpPost]
public JsonResult Upload(HttpPostedFileBase file)
{
    if (file != null && file.ContentLength > 0)
    {
        //Da ich aktuell nicht weiß wie ich ebenfalls z.B. "UploadPerson" direkt im Upload mit
        //"befüllen" lassen kann füllen wir dieses Model erst einmal per "Hand".
        var json = HttpContext.Request.Form["person"];
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        UploadPerson person = (UploadPerson)serializer.Deserialize(json, typeof(UploadPerson));
        //TODO etwas mit den Personendaten machen.

        var fileName = Path.GetFileName(file.FileName);
        var path = Path.Combine(Server.MapPath("~/Images/"), fileName);
        file.SaveAs(path);
    }

    return Json(true, JsonRequestBehavior.AllowGet);
}
public class UploadPerson
{
    public string Name { get; set; }

    public string Email { get; set; }
}

Nach dem auf der .NET Seite alle Funktionen und Klassen umgesetzt sind, fehlt nur noch der HTML und JavaScript Part.

Im HTML Definieren wir unsere Eingabefelder wie FileUpload und Textfelder für unser Person Objekt

<div ng-app="uploadApp" ng-controller="myCtrl">
    <div class="row">
        <div class="col-md-12">
            <h3>Datei Upload mit AngularJS</h3>
        </div>
        <hr />
    </div>
    <div class="row form-horizontal">
        <div class="form-group">
            <label class="col-sm-2 control-label">File Upload 1</label>
            <div class="col-sm-10">
                <input class="form-control" type="file" file-model="ViewModel.myFile" />
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">Name</label>
            <div class="col-sm-10">
                <input class="form-control" type="text" ng-model="ViewModel.Person.Name" />
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">Email</label>
            <div class="col-sm-10">
                <input class="form-control" type="email" ng-model="ViewModel.Person.Email" />
            </div>
        </div>
    </div>
    <div class="row">
        <br />
        <div class="col-md-2">
            <button ng-click="uploadFile()" class="btn btn-default">Datei hochladen</button>
        </div>
    </div>
</div>

Dann fehlt nur noch der passende JavaScript Code.

<script type="text/javascript">
    var app = angular.module("uploadApp", []);
    app.controller("myCtrl", function ($scope, fileUpload) {
        $scope.ViewModel = {};
        $scope.ViewModel.myFile = [];
        $scope.ViewModel.Person = {};
        $scope.ViewModel.Person.Name = "SquadWuschel";
        $scope.ViewModel.Person.Email = "SquadWuschel@@Test.de";
        $scope.uploadFile = function () {
            fileUpload.uploadFileToUrl($scope.ViewModel.myFile, $scope.ViewModel.Person, "Upload");
        }
    });

    app.directive('fileModel', [
        '$parse', function ($parse) {
            return {
                restrict: 'A',
                link: function (scope, element, attrs) {
                    var model = $parse(attrs.fileModel);
                    var modelSetter = model.assign;
                    element.bind('change', function () {
                        scope.$apply(function () {
                            modelSetter(scope, element[0].files[0]);
                        });
                    });
                }
            };
        }
    ]);

    app.service('fileUpload', [
        '$http', '$log', function ($http, $log) {
            this.uploadFileToUrl = function (file, personData, uploadUrl) {
                var formData = new FormData();
                //Unsere Datei hinzufügen
                formData.append('file', file);
                //Unsere Personendaten ebenfalls den Formdaten hinzufügen.
                formData.append('person', angular.toJson(personData)); 
                $http.post(uploadUrl, formData, {
                    transformRequest: angular.identity,
                    headers: { 'Content-Type': undefined }
                })
                    .success(function (data) {
                        $log.log("Upload war erfolgreich");
                    }).error(function () {
                        $log.log("Fehler beim Upload der Daten");
                    });
            };
        }
    ]);
</script>

Im Code ist eine Direktive “fileModel” enthalten die das Äquivalent zum “ngModel” für unser Input vom Typ “file” darstellt. In meinem Beispiel wird also in der Variable “ViewModel.myFile” die entsprechende Datei hinterlegt die ausgewählt wurde.

Im Service werden dann alle Formulardaten an den Server gesendet. Ich füge den Formdaten die Datei aus dem Upload Element hinzu und dann noch die Personendaten.

Das Beispiel findet Ihr auch bei mir auf Codeplex.

TFS Online von Microsoft oder doch eher Codeplex.com


Sobald man auch privat noch etwas programmiert, hat man meist den Anspruch seinen Quellcode auch irgendwo „sicher“ abzulegen.

Entweder man entscheidet sich daheim seine eigene Quellcodeverwaltung zu installieren, was dank „Team Foundation Server 2013 Express“ für kleine Teams bis 5 Mitarbeiter auch kostenlos möglich ist oder man verwendet eine Online Variante des TFS.

Die Online Variante hat den Vorteil, dass man immer und überall auf seine Quellcodes Zugriff hat. Ich verwende persönlich zwei verschiedene Anbieter um meinen Quellcodes Online abzulegen.

Zum einen benutze ich Codeplex (https://www.codeplex.com/) um alle Öffentlich zugänglichen Projekte abzulegen, denn auf Codeplex dürfen nur Öffentlich zugängliche Projekte abgelegt werden bzw. die Projekte müssen spätestens nach X Tagen veröffentlicht werden.

Dann benutze ich auch noch die Online Variante des TFS (http://www.visualstudio.com/en-us/products/visual-studio-online-user-plans-vs.aspx) der von Microsoft zur Verfügung gestellt wird und ebenfalls für Teams bis zu 5 Personen kostenlos genutzt werden kann.

Hier lege ich alle privaten Projekte ab die ich nicht der Öffentlichkeit „präsentieren“ möchte. Persönlich finde ich die Online Variante des TFS von Microsoft auch noch etwas praktischer, da man hier auf sehr viele nützliche Features der aktuellen TFS Version zugreifen kann.

Wie man sieht muss man sich nur entscheiden was man genau mit seinen Quellcodes machen möchte. Ob man sie der Öffentlichkeit zur Verfügung stellen will oder eher nur für sich privat nutzen möchte, für beide Varianten gibt es mindestens eine kostenlose Onlinelösung. Beide Anbieter lassen sich auch Problemlos im Visual Studio als Quellcodeverwaltung einstellen.

Natürlich gibt es noch eine Menge andere Anbieter wie z.B. GitHub und Subversion, mit beiden hatte ich bisher eher wenig Kontakt und bleiben für mich aktuell außen vor.

AngularJS – wichtige Links und Toolsets


Wenn man sich in ein neues Framework einlesen / einarbeiten muss, ist es oft schwer einen guten Einstieg zu finden. Daher im Folgenden eine kleine Sammlung an interessanten Links zu AngularJS.

Meine Projekte setzen sich aktuell aus den folgenden Frameworks / Technologien zusammen:

  • ASP.NET MVC zum Bereitstellen der AJAX Daten klassisch mit Controllern und Models
  • AngularJS zum Anzeigen / Manipulieren der Daten
  • Bootstrap für das Layout

Für AngularJS selbst gibt es im Netz ein paar sehr gute auch kostenlose Video Tutorials, die für den Anfang bzw. auch für Fortgeschrittene immer wieder was neues zu bieten haben.

Zum einen von egghead.io – hier gibt es eine Menge kostenloser Videos von John Lindquist – meine Empfehlung die Sortierung auf “Sort by: Earliest” einstellen und dann einfach von vorn beginnen, desto weiter Ihr zu den aktuellen Einträgen vorstoßt, sind vermehrt kostenpflichtige Videos dabei, aber immer noch genug die nichts kosten. Hier gibt es inzwischen auch einen YouTube Channel mit allen Videos.

Die andere Videoquelle die ich sehr brauchbar fand ist ein YouTube Channel mit 51 AngularJS Videos die alle sehr informativ für Anfänger und Neueinsteiger sind und auch folgende “All you need to know about AngularJS” YouTube Videos sind sehr gut.

Außerdem bietet AngularJS selbst auch einen Youtube Channel an wo es auch noch einmal eine Menge zu sehen gibt. von kurzen Clips bis hin zu langen Sessions von einer Stunde oder mehr.

Wenn man aus dem ASP.NET MVC Bereich kommt, gibt es auch ein sehr gutes Einführungsvideo wie man eine ASP.NET MVC Anwendung in eine AngularJS Anwendung umschreibt.

Weitere AngularJS Links:

  1.  Große Linksammlung zu AngularJS Themen auf github
  2. Übersicht über viele AngularJS Variablen und Funktionen bei cheatography
  3. Eine Gute Übersicht für Code Guidelines mit AngularJS, wenn man schon etwas weiter vorangeschritten ist.
  4. Einführung in Services und Factories von AngularJS
  5. Einführung in Direktiven mit AngularJS
  6. Eine sehr gute Übersicht über Form Validierung mit AngularJS

Da ich außerdem sehr gerne mit Bootstrap arbeite gibt es auch für Bootstrap noch zwei sehr gute Implementierungen die das JavaScript von Bootstrap quasi “ersetzten” und alles im AngularJS Style mit Direktiven umsetzten und Sie bieten außerdem noch ein paar zusätzliche Controls an.

  1. Angular UI-Bootstrap
  2. Angular Strap

Bisher habe ich zwar nur AngularUI für Bootstrap verwendet, da diese Umsetzung direkt vom AngularJS Team kommt aber Angular Strap ist in seiner neuesten Version auch komplett mit AngularJS umgesetzt und benötigt kein jQuery mehr. Außerdem bietet Angular Strap mehr zusätzliche Controls an. Leider weiß ich nicht ob man beide Versionen gefahrenlos im gleichen Projekt benutzen kann. Wenn man in seinem Projekt jedoch AngularJS und Boostrap verwendet, sollte man auf jeden Fall eine der beiden Implementierungen verwenden und nicht die Original JavaScript Implementierung von Bootstrap.

Dann gibt es noch eine Sammlung aus nützlichen Direktiven – AngularUI nicht zu verwechseln mit “UI-Bootstrap” was aber ebenfalls mit in der Sammlung aus nützlichen Direktiven enthalten ist.

Das sind so meine wichtigsten Anlaufstellen und Erweiterungen die ich aktuell für die Entwicklung von Webseiten verwende. Wenn Ich was vergessen haben sollte oder Ihr noch weitere gute Links habt, dann postet diese einfach.

Eigene Domain für meinen Blog – squadwuschel.de


So, jetzt gibt es meinen Blog auch direkt unter einer eigenen Domain

http://squadwuschel.de

die bisherige Domain https://squadwuschel.wordpress.com von WordPress leitet jetzt direkt auf die neue Domain um. Beim Rest bleibt alles beim alten.

Mit der Umstellung muss ich wohl noch 72 Stunden warten, da es sonst ein Glücksspiel ist das man noch auf meine Seite kommt.