Ich habe einen Web-API-Dienstaufruf, der die Einstellungen eines Benutzers aktualisiert. Wenn ich diese POST - Methode von einem jQuery-ajax-Aufruf aus aufrufe, sind die Eigenschaften des Anforderungsparameterobjekts leider immer NULL (oder Standardwerte) und nicht die übergebenen. Wenn ich dieselbe Methode mit REST client (ich verwende Postman), es funktioniert wunderbar. Ich kann nicht herausfinden, was ich falsch damit mache, aber ich hoffe, jemand hat das schon mal gesehen. Es ist ziemlich einfach ...
Hier ist mein Anfrageobjekt:
public class PreferenceRequest
{
[Required]
public int UserId;
public bool usePopups;
public bool useTheme;
public int recentCount;
public string[] detailsSections;
}
Hier ist meine Controller-Methode in der UserController-Klasse:
public HttpResponseMessage Post([FromBody]PreferenceRequest request)
{
if (request.systemsUserId > 0)
{
TheRepository.UpdateUserPreferences(request.UserId, request.usePopups, request.useTheme,
request.recentCount, request.detailsSections);
return Request.CreateResponse(HttpStatusCode.OK, "Preferences Updated");
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.NotAcceptable, "You must provide User ID");
}
}
Hier ist mein Ajax-Anruf:
var request = {
UserId: userId,
usePopups: usePopups,
useTheme: useTheme,
recentCount: recentCount,
detailsSections: details
};
$.ajax({
type: "POST",
data: request,
url: "http://localhost:1111/service/User",
success: function (data) {
return callback(data);
},
error: function (error, statusText) {
return callback(error);
}
});
Ich habe versucht, dataType & contentType auf verschiedene Dinge einzustellen ('json', 'application/json' usw.), aber die Eigenschaften des Anforderungsobjekts sind immer voreingestellt oder null. Wenn ich zum Beispiel dieses Objekt übergebe:
var request = {
UserId: 58576,
usePopups: false,
useTheme: true,
recentCount: 10,
detailsSections: ['addresses', 'aliases', 'arrests', 'events', 'classifications', 'custody', 'identifiers', 'phone', 'remarks', 'watches']
}
Ich kann ein vollständig aufgefülltes Anforderungsobjekt mit den gültigen Werten wie oben aufgeführt sehen. Im Web-API-Controller ist die Anforderung jedoch vorhanden, die Eigenschaften lauten jedoch wie folgt:
UserId: 0,
usePopups: false,
useTheme: false,
recentCount: 0,
detailsSections: null
Zu Ihrer Information - Ich mache mit diesem Projekt keine ASP.Net MVC- oder ASP.NET-Seiten. Ich verwende nur die Web-API als Dienst und mache alle Aufrufe mit jQuery $ .ajax.
Irgendeine Idee, was ich hier falsch mache? Vielen Dank!
UPDATE: Ich möchte nur anmerken, dass ich in diesem Web-API-Projekt viele Methoden in anderen Controllern habe, die dies tun genau dasselbe und ich die exakt gleiche Weise und benenne Sie arbeiten einwandfrei! Ich habe den Morgen damit verbracht, die verschiedenen Aufrufe zu vergleichen, und es scheint keinen Unterschied in der Methode oder in den Kopfzeilen zu geben, und trotzdem funktioniert es bei dieser bestimmten Methode einfach nicht.
Ich habe auch versucht, zu einer Put-Methode zu wechseln, aber ich erhalte genau dieselben Ergebnisse - das Anforderungsobjekt kommt zwar herein, wird aber nicht mit den korrekten Werten gefüllt. Was so frustrierend ist, ist, dass ich ungefähr 20 Controller-Klassen in diesem Projekt habe und die Posts in all diesen ...
Dies scheint ein allgemeines Problem in Bezug auf Asp.Net WebAPI zu sein.
Die Ursache für Nullobjekte ist im Allgemeinen die Deserialisierung des Json-Objekts in das C # -Objekt. Leider ist das Debuggen sehr schwierig - und Sie können herausfinden, wo Ihr Problem liegt.
Ich ziehe es vor, einfach den vollständigen Json als Objekt zu senden und dann manuell zu deserialisieren. Zumindest auf diese Weise erhalten Sie echte Fehler anstelle von Nullen.
Wenn Sie Ihre Methodensignatur ändern, um ein Objekt zu akzeptieren, verwenden Sie JsonConvert:
public HttpResponseMessage Post(Object model)
{
var jsonString = model.ToString();
PreferenceRequest result = JsonConvert.DeserializeObject<PreferenceRequest>(jsonString);
}
Vielleicht hilft es, ich hatte das gleiche Problem.
Alles funktionierte gut, und plötzlich waren alle Eigenschaften standardmäßig aktiviert.
Nach einem kurzen Test stellte ich fest, dass es das [Serializable] war, das das Problem verursachte :
public IHttpActionResult Post(MyComplexClass myTaskObject)
{
//MyTaskObject is not null, but every member are (the constructor get called).
}
und hier war ein Ausschnitt aus meiner Klasse:
[Serializable] <-- have to remove that [if it was added for any reason..]
public class MyComplexClass()
{
public MyComplexClass ()
{
..initiate my variables..
}
public string blabla {get;set;}
public int intTest {get;set;
}
Mit dieser von @blorkfish geposteten Technik hat es gut funktioniert:
public HttpResponseMessage Post(Object model)
{
var jsonString = model.ToString();
PreferenceRequest result = JsonConvert.DeserializeObject<PreferenceRequest>(jsonString);
}
Ich hatte ein Parameterobjekt, das einige native Typen und einige weitere Objekte als Eigenschaften hatte. Die Objekte hatten interne Konstruktoren und der JsonConvert.DeserializedObject-Aufruf auf dem JsonString hat den Fehler ausgegeben:
Konnte keinen Konstruktor für den Typ ChildObjectB finden. Eine Klasse sollte entweder einen Standardkonstruktor haben, einen Konstruktor mit Argumente oder ein Konstruktor, der mit dem JsonConstructor-Attribut markiert ist.
Ich habe die Konstruktoren in public geändert, und das Parameterobjekt wird jetzt aufgefüllt, wenn der Objektmodellparameter durch das reale Objekt ersetzt wird. Vielen Dank!
Ich denke, das Problem ist, dass Ihr Controller den Inhaltstyp [FromBody] erwartet. Versuchen Sie, Ihren Controller in zu ändern
public HttpResponseMessage Post(PreferenceRequest request)
und Ajax zu
$.ajax({
type: "POST",
data: JSON.stringify(request);,
dataType: 'json',
contentType: "application/json",
url: "http://localhost:1111/service/User",
Übrigens kann das Erstellen von Modellen in Javascript nicht die beste Methode sein.
Es gibt also 3 mögliche Probleme, bei denen der Wert nicht bindet:
Ich überlege, ob API-Aufrufe einen Filter anwenden sollten, der einen Fehler zurückgibt, wenn die Bindung einen Fehler ergibt!
Ich bin auch mit diesem Problem konfrontiert und nach vielen Stunden von Debbug und Recherchen kann feststellen, dass das Problem nicht durch die Attribute Content-Type oder Type $ Ajax verursacht wurde. Das Problem wurde durch NULL-Werte für mein JSON-Objekt verursacht POST macht auch nichts, aber sobald die NULL-Werte festgelegt wurden, war POST in Ordnung und wurde nativ in meine Klasse "respuestaComparacion" eingefügt. Hier der Code:
JSON
respuestaComparacion: {
anioRegistro: NULL, --> cannot cast to BOOL
claveElector: NULL, --> cannot cast to BOOL
apellidoPaterno: true,
numeroEmisionCredencial: false,
nombre: true,
curp: NULL, --> cannot cast to BOOL
apellidoMaterno: true,
ocr: true
}
Regler
[Route("Similitud")]
[HttpPost]
[AllowAnonymous]
public IHttpActionResult SimilitudResult([FromBody] RespuestaComparacion req)
{
var nombre = req.nombre;
}
Klasse
public class RespuestaComparacion
{
public bool anioRegistro { get; set; }
public bool claveElector { get; set; }
public bool apellidoPaterno { get; set; }
public bool numeroEmisionCredencial { get; set; }
public bool nombre { get; set; }
public bool curp { get; set; }
public bool apellidoMaterno { get; set; }
public bool ocr { get; set; }
}
Ich hoffe das hilft.
Ein bisschen zu spät zur Party, aber ich hatte das gleiche Problem und der Fix deklarierte den contentType in Ihrem Ajax-Aufruf:
var settings = {
HelpText: $('#help-text').val(),
BranchId: $("#branch-select").val(),
Department: $('input[name=departmentRadios]:checked').val()
};
$.ajax({
url: 'http://localhost:25131/api/test/updatesettings',
type: 'POST',
data: JSON.stringify(settings),
contentType: "application/json;charset=utf-8",
success: function (data) {
alert('Success');
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
Und Ihr API-Controller kann folgendermaßen eingerichtet werden:
[System.Web.Http.HttpPost]
public IHttpActionResult UpdateSettings([FromBody()] UserSettings settings)
{
//do stuff with your UserSettings object now
return Ok("Successfully updated settings");
}
Ich weiß, das ist ein bisschen spät, aber ich bin gerade auf das gleiche Problem gestoßen. @Blorkfishs Antwort funktionierte auch für mich, führte mich jedoch zu einer anderen Lösung. Einem der Teile meines komplexen Objekts fehlte ein parameterloser Konstruktor. Nach dem Hinzufügen dieses Konstruktors funktionierten sowohl die Put- als auch die Post-Anforderung wie erwartet.
Ich bin auf das gleiche Problem gestoßen. Die erforderliche Korrektur bestand darin, sicherzustellen, dass alle serialisierbaren Eigenschaften für die JSON-Parameterklasse erhalten wurden. einstellen; explizit definierte Methoden. Verlassen Sie sich nicht auf die automatische Eigenschafts-Syntax von C #! Hoffe, das wird in späteren Versionen von asp.net behoben.
In meinem Fall wurde das Problem gelöst, als ich hinzufügte
hol {} set {}
zur Definition der Parameterklasse:
public class PreferenceRequest
{
public int UserId;
public bool usePopups {get; set;}
public bool useTheme {get; set;}
public int recentCount {get; set;}
public string[] detailsSections {get;set;}
}
statt:
public class PreferenceRequest
{
[Required]
public int UserId;
public bool usePopups;
public bool useTheme;
public int recentCount;
public string[] detailsSections;
}
Ich bin auf das gleiche Problem gestoßen, die Lösung für mich bestand darin, sicherzustellen, dass die Typen meiner Klassenattribute mit den json-Attributen übereinstimmen, meine ich
Json: "attribute": "true"
Sollte als Zeichenfolge und nicht als boolean behandelt werden, sieht aus, als würden bei einem solchen Problem alle Attribute unter dem fehlerhaften Attribut auf null gesetzt
Mein Problem wurde durch keine der anderen Antworten gelöst, daher ist diese Lösung eine Überlegung wert:
Ich hatte die folgende DTO- und Controller-Methode:
public class ProjectDetailedOverviewDto
{
public int PropertyPlanId { get; set; }
public int ProjectId { get; set; }
public string DetailedOverview { get; set; }
}
public JsonNetResult SaveDetailedOverview(ProjectDetailedOverviewDto detailedOverview) { ... }
Da mein DTO eine Eigenschaft mit dem gleichen Namen wie der Parameter hatte (detailOverview), wurde der Deserialisierer verwirrt und versuchte, den Parameter mit dem String und nicht mit dem gesamten komplexen Objekt zu füllen. Die Lösung bestand darin, den Namen des Parameterparameter des Controllers auf 'overview'
, sodass der Deserialiser wusste, dass ich nicht versucht habe, auf die Eigenschaft zuzugreifen.
Ich stehe vor diesem Problem
so wie das
var json = JsonConvert.SerializeObject(yourobject);
var stringContent = new StringContent(json, UnicodeEncoding.UTF8, "application/json");
var response = await client.PostAsync ("apiURL", stringContent);
Ich bin heute auch auf das gleiche Problem gestoßen. Nachdem Sie alle diese Funktionen ausprobiert, die API von Azure und die Xamarin Android-App debuggt haben, stellt sich heraus, dass es sich um ein Referenz-Update-Problem handelt. Denken Sie daran, sicherzustellen, dass das Newtonsoft.JSON NUGET-Paket für Ihre API aktualisiert wurde (falls Sie dies verwenden).
HttpGet
public object Get([FromBody]object requestModel)
{
var jsonstring = JsonConvert.SerializeObject(requestModel);
RequestModel model = JsonConvert.DeserializeObject<RequestModel>(jsonstring);
}
Heute habe ich das gleiche Problem wie du. Wenn ich eine POST
-Anforderung von ajax
sende, erhält der Controller ein leeres Objekt mit Null
und Standardeigenschaftswerten . Die Methode lautet:
[HttpPost]
public async Task<IActionResult> SaveDrawing([FromBody]DrawingModel drawing)
{
try
{
await Task.Factory.StartNew(() =>
{
//Logic
});
return Ok();
}
catch(Exception e)
{
return BadRequest();
}
}
Mein Content-Type
war korrekt und alles andere war auch korrekt. Nachdem ich viele Dinge ausprobiert hatte, stellte ich fest, dass das Objekt folgendermaßen gesendet wurde:
$.ajax({
url: '/DrawingBoard/SaveDrawing',
type: 'POST',
contentType: 'application/json',
data: dataToPost
}).done((response) => { });
Funktioniert nicht, aber das Senden auf diese Weise hat stattdessen funktioniert:
$.ajax({
url: '/DrawingBoard/SaveDrawing',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(dataToPost)
}).done((response) => { });
Ja, die fehlende JSON.stringify()
verursachte das ganze Problem und es war nicht nötig, =
oder irgendetwas anderes als Präfix oder Suffix an JSON.stringify
..__ zu setzen. Ich habe festgestellt, dass das Format der Anforderungsnutzdaten zwischen den beiden Anforderungen völlig unterschiedlich ist
Dies ist die Anforderungsnutzlast mit JSON.stringify
.
Und dies ist die Anforderungsnutzlast ohne JSON.stringify
Und vergessen Sie nicht, wenn die Dinge magisch werden und Sie Google Chrome
verwenden, um Ihre Webanwendung zu testen. Leere Cache und hartes Nachladen von Zeit zu Zeit.
Da mich dieses Thema gestern fast für einen ganzen Arbeitstag beschäftigte, möchte ich etwas hinzufügen, das anderen in derselben Situation helfen könnte.
Ich habe mit Xamarin Studio mein Winkel- und Web-API-Projekt erstellt. Beim Debuggen kam das Objekt manchmal durch Null und zu anderen Zeiten als aufgefülltes Objekt. Erst als ich mit dem Debuggen meines Projekts in Visual Studio begonnen habe, wurde das Objekt bei jeder Post-Anforderung gefüllt. Dies scheint ein Problem beim Debuggen in Xamarin Studio zu sein.
Versuchen Sie bitte, in Visual Studio zu debuggen, wenn dieses Nullparameterproblem mit einer anderen IDE auftritt.