MVC WebAPI und Serialisieren von Eingabedaten ohne Form Submit


Die Tage hatte ich das Problem, dass ich auf einer Seite noch ein paar Eingabefelder für einen Filter unterbringen musste. Es war mir leider nicht möglich ein zweites Form Tag dafür zu erstellen, daher habe ich die Elemente mit in das Hauptformular übernommen.

Ich benötigte für meinen Ajax Request an die WebAPI aber nur die Eingabefelder für meinen Filter und nicht die gesamten Formulardaten und ich wollte auch nicht jedes Eingabefeld einzeln heraussuchen und die Werte per Hand zusammensetzten.

Wenn man dann weiß das man mit jQuery problemlos Formulare Serialisieren kann und man kurz im Internet sucht, findet man auch schnell eine Möglichkeit wie man nur bestimmte Eingabefelder serialisieren kann ohne dabei das ganze Formular zu nutzen. Ich habe einfach um meine Suchfelder ein DIV mit einer ID gesetzt und dann per jQuery und einem passenden Selector die passenden Daten erhalten.

<input id="currentDate" class="span35" type="date" name="currentDate">

<div id="searchDiv" class="well well-small">
  <div class="btn-block">
    <select id="FilterWorktimeTypeList" class="span42" name="FilterWorktimeTypeList">
   </div>
   <div class="input-append btn-block">
     <input id="filterText" class="span35" type="text" name="SearchText">
     <button id="filterBtn" class="btn" type="button">Filtern</button>
  </div>
</div>

Da currentDate nicht innerhalb unseres SuchDIVs liegt, müssen wir den Inhalt, danach per Hand zu unseren Daten hinzufügen. Wichtig ist, das jedes Eingabefeld einen Namen hat, denn sonst wird es nicht serialisieren. Außerdem kann nicht die Hausmethode von jQuery zum serialisieren verwendet werden, sondern die Funktion “serializeObject” muss verwendet werden und erst in Verbindung mit “JSON.stringify” wird unser Datenobjekt auch von der WebAPI “erkannt”.

//wir suchen alle Inputfelder unterhalb unseres Divs heraus.
var searchDiv = $("#searchDiv :input")
//Wir serealisieren erst unser "Formular" aka unser SuchDiv
var jsonData = searchDiv.serializeObject();
//Da im Suchdiv nicht unser Datum mit enthalten ist, fügen wir es unserem Objekt mit hinzu.
jsonData["Datum"] = $("#currentDate").val();
//Wir müssen unsere serealisieren Daten noch so umwandeln, das diese auch von der WebAPI erkannt werden
jsonData = JSON.stringify(jsonData);

Die Funktion “serializeObject” habe ich im Netz gefunden und funktioniert wunderbar. Die Funktion selbst greift auf die jQuery Funktion “serializeArray” zurück. Diese Standardfunktion reicht leider nicht aus um ein gültiges Objekt zu erstellen, was die WebAPI als Objekt erkennt und umwandelt.

//jQuery Plugin um z.B. direkt Inputfelder und derren Inhalt zu serealisieren als Objekt!
//http://stackoverflow.com/questions/1184624/convert-form-data-to-js-object-with-jquery
$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

Damit die Daten dann auch entsprechend an die WebAPI als Model übergeben werden können benötigen wir ein passendes C# Model für die Daten.

public class WorktimeEntryFilterModel
{
  /// <summary>
  /// Der Text nach dem gesucht werden soll.
  /// </summary>
  public string SearchText { get; set; }

  /// <summary>
  /// Die ausgewählte ID der WorktimeTypeList für die Filter
  /// </summary>
  public int? FilterWorktimeTypeList { get; set; }

  /// <summary>
  /// Der Datumsstring aus dem Model.
  /// </summary>
  public string Datum { get; set; }
}

Wichtig ist, das ich bei meinen WebAPI Aufrufen eine extra Route eingebunden habe in der WebApiConfig, wieso und weshalb das könnt Ihr hier in einem anderen Artikel nachlesen.

Der Beispielhafte Aufruf unserer Daten “jsonData” kann dann z.B. folgendermaßen aussehen.

$.ajax({
   url: "/api/worktimeApi/ByTextFilter/@Model.UserId",
   type: "POST",
   data: jsonData
   contentType: 'application/json; charset=utf-8',
   statusCode: {
        200 /* OK */: function(daten) {
            //Do some fun with the Data
            }
   }
});

und die passende WepAPI Funktion die unsere Daten entgegennimmt und verarbeitet.

/// <summary>
/// Filtert den Eintrag nach den übergebenen Modeldaten
/// </summary>
/// <param name="id">Die UserId nach der gefiltert werden soll</param>
/// <param name="value">Unsere Modeldaten nach denen gefiltert werden soll</param>
public HttpResponseMessage ByTextFilter(long id, WorktimeEntryFilterModel value)
{
    if (value != null)
    {
        WorktimeListModel worktime = new WorktimeListModel(id, value);
        worktime.FilterWorktimeList();

        //Wird automatisch in JSON Objekt umgewandelt und gibt den StatusCode 200 für OK zurück!
        HttpResponseMessage response = Request.CreateResponse<WorktimeListModel>(HttpStatusCode.OK, worktime);
        response.Headers.Location = new Uri(Request.RequestUri, string.Format("/api/WorktimeApi/ByTextFilter/{0}", id.ToString()));
        return response;
    }

    throw new HttpResponseException(HttpStatusCode.BadRequest);
}

Damit ist es problemlos möglich nur kleine Teile eines großen Formulars zu benutzten. Vielleicht existiert auch kein Formular und damit hat man die Möglichkeit die Daten trotzdem problemlos zu serialisieren und zu versendet.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s