2012-04-04 6 views
4

Ich bin neu in KockoutJS, so dass ich etwas Einfaches vermisse.KnockoutJS postJSON-Methode entgeht meiner Zeichenfolge warum?

Ich habe ein Textfeld in einem Formular:

<form method="POST" data-bind="submit: save" id="theForm"> 
    <textarea name="Text" rows="10" cols="100" data-bind="value: userText" ></textarea> 
    <input type="submit" value="Save" /> 
</form> 

Und ich habe den folgenden Knockout-Code:

<script type="text/javascript"> 
    var MyViewModel = { 
     userText: ko.observable('@Model.UserText'), 
     save: function() { 
       ko.utils.postJson('@Url.Action("modify")',{userText : this.userText}); 
      } 
    } 
</script> 

Wo @Model.UserText eine Zeichenkette ist. und meine ASP.NET MVC-Controller-Methode modify ist wie folgt definiert:

[Authorize] 
[HttpPost] 
public ActionResult Modify(string userText) 
{ 
    ... 
} 

Mein Problem ist, dass Die postJSON Methode entsendet einen maskierten String zu meiner Controller-Methode, und ich verstehe nicht, warum. ich in Fiedler sehen kann, dass die Zeichenfolge kommt in als userText=%22some+text%22

wenn ich Ajax normalen jQuery anstelle von postJson wie folgt aus:

$.ajax(
{ 
url: '@Url.Action("modify")', 
contentType: 'application/json', 
type: 'POST', 
data: ko.toJSON({userText: ko.toJS(this.userText)}), 
success: function(result) { 
    ko.mapping.updateFromJS(this, result); 
} 
}); 

dann das JSON-Objekt {'userText': 'some text'} an die Steuerung Methode übergeben wird und Der MVC-Modellbinder analysiert dies korrekt und gibt mir eine nicht-dekomprimierte Zeichenfolge.

Kann ich postJson dasselbe JSON-Objekt übergeben, das von der jQuery ajax-Methode übergeben wird?

Antwort

7

Vollständige Informationen in diesem Artikel befindet sich http://blog.stevensanderson.com/2010/07/12/editing-a-variable-length-list-knockout-style/

Was Sie brauchen, ist [FromJson] auf der action-Attribut zu verwenden.

[Authorize] 
[HttpPost] 
public ActionResult Modify([FromJson]string userText) 
{ 
    ... 
} 

Implementierung für atttribute:

using System.Web.Mvc; 
using System.Web.Script.Serialization; 

namespace koListEditor 
{ 
    public class FromJsonAttribute : CustomModelBinderAttribute 
    { 
     private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer(); 

     public override IModelBinder GetBinder() 
     { 
      return new JsonModelBinder(); 
     } 

     private class JsonModelBinder : IModelBinder 
     { 
      public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
      { 
       var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName]; 
       if (string.IsNullOrEmpty(stringified)) 
        return null; 
       return serializer.Deserialize(stringified, bindingContext.ModelType); 
      } 
     } 
    } 
} 

Nur ein paar Kommentare:

ko.utils.postJson (urlOrForm, Daten, Optionen) wird für Sie folgendes:

1) es wird ein internes Formular mit einem Satz von Eingängen

erstellen 210

2) es iteriert Ihren Datenparameter und ruft auf ko.utils.stringifyJson (ko.utils.unwrapObservable (data [key]));

für jede Eigenschaft und speichert das Ergebnis für diese Eingabe. Diese intern verwendet JSON.stringify, so in Ihrem Fall wird es

JSON.stringify('"some text"') 

nennen Deshalb sollten Sie die Zeichenfolge sehen 'entkommen' (es eigentlich nur umgewandelt in JSON)

3) falls Sie übergeben Optionen mit Params, es wird sie auch für die Anfrage anhängen.

Beispiele:

ko.utils.postJson('localhost',{ userText : '"some text"' }); 

Beiträge: usertext "\" some text \ ""

ko.utils.postJson('localhost',{}, {params: { userText : '"some text"' } }); 

Beiträge: usertext "some text"

so in Wenn Sie nicht mit [FromJson] dekorieren möchten, können Sie einfach eine Anzeige erstellen d an options.params anstelle von Daten. Wenn Sie ein komplexeres Json-Objekt übergeben müssen (nicht eine einfache Zeichenfolge, sondern ein ViewModel), müssen Sie dieses [FromJson] -Attribut weiterhin verwenden.

+0

Vielen Dank. mit der Syntax {params: {}} funktionierte. Ich wollte meine MVC-Controller-Methode nicht mit [fromJSON] dekorieren. Ich denke eigentlich, dass der normale jQuery Ajax-Ansatz klarer zu lesen ist, also denke ich, dass ich am Ende diesen Weg gehen werde. –

+0

Ich benutze auch immer pure jquery ajax Ansatz. Aus meiner Sicht ist der einzige Grund für die Verwendung von ko.utils.postJson, wenn Sie einen echten Formular-Post, z. um Dinge wie RedirectToAction in Ihrem Controller zu verwenden oder um nur die vollständige (nicht-partielle) Ansicht zurückzugeben. Aber diese Anwendungsfälle sind ziemlich selten ... – Artem

+0

Wenn Sie [ValidateAntiForgeryToken] in Ihrer Controller-Postaktion verwenden, können Sie diesen Trick verwenden, um das Token zu senden: params: {__RequestVerificationToken: $ ('input [name = __ RequestVerificationToken]') .val()} – jgarza