c# - Call Post method having multiple parameters in cshtml file -
i have declared method in mvc webapi as:
[route("api/user/loginuser")] public string postlogin(string email, string password, string authkey) { // return ""; } now in cshtml file testing purpose calling method as:
function loginuser() { $.ajax({ url: baseurl + "api/user/loginuser", type: "post", contenttype: 'application/json; charset=utf-8', data: json.stringify({ email: "xyz@gmail.com", password: "password", authkey: "1234" }), datatype: 'json', success: function (data) { // soemthing }, fail: function (data) { // failed } }); } but api never called. not getting problem. please me, stuck bigtime here.
thanx in advance. kind of appreciated.
let's make little examination. creating new webapi project, create testcontroller extending apicontroller, make method model in it
[httppost] public string something(string name, string age) { return "smth"; } now compile application , open localhost/help
there's documentation available method. our test controller documented. let's see what's there:
test api description post api/test?name={name}&age={age} no documentation available. it seems mulitple params automatically mapped parameters instead extracted key/value pairs post request body. because of default httpparameterbinding , if want change it, need extend it, override things , tell app use crafted override of httpparameterbinding.
luckily, there's blogpost regarding how create own parameter binding ( http://weblog.west-wind.com/posts/2012/sep/11/passing-multiple-simple-post-values-to-aspnet-web-api )
all credits given author of blogpost, paste of code, if link gets broken.
create class somewhere in application extends httpparameterbinding
public class simplepostvariableparameterbinding : httpparameterbinding { private const string multiplebodyparameters = "multiplebodyparameters"; public simplepostvariableparameterbinding(httpparameterdescriptor descriptor) : base(descriptor) { } /// <summary> /// check simple binding parameters in post data. bind post /// data query string data /// </summary> /// <param name="metadataprovider"></param> /// <param name="actioncontext"></param> /// <param name="cancellationtoken"></param> /// <returns></returns> public override task executebindingasync(modelmetadataprovider metadataprovider, httpactioncontext actioncontext, cancellationtoken cancellationtoken) { string stringvalue = null; namevaluecollection col = tryreadbody(actioncontext.request); if (col != null) stringvalue = col[descriptor.parametername]; // try reading query string if have no post/put match if (stringvalue == null) { var query = actioncontext.request.getquerynamevaluepairs(); if (query != null) { var matches = query.where(kv => kv.key.tolower() == descriptor.parametername.tolower()); if (matches.count() > 0) stringvalue = matches.first().value; } } object value = stringtotype(stringvalue); // set binding result here setvalue(actioncontext, value); // now, can return completed task no result taskcompletionsource<asyncvoid> tcs = new taskcompletionsource<asyncvoid>(); tcs.setresult(default(asyncvoid)); return tcs.task; } /// <summary> /// method implements parameter binding hookup global configuration object's /// parameterbindingrules collection delegate. /// /// routine filters based on post/put method status , simple parameter /// types. /// </summary> /// <example> /// globalconfiguration.configuration. /// .parameterbindingrules /// .insert(0,simplepostvariableparameterbinding.hookupparameterbinding); /// </example> /// <param name="descriptor"></param> /// <returns></returns> public static httpparameterbinding hookupparameterbinding(httpparameterdescriptor descriptor) { var supportedmethods = descriptor.actiondescriptor.supportedhttpmethods; // apply binder on post , put operations if (supportedmethods.contains(httpmethod.post) || supportedmethods.contains(httpmethod.put)) { var supportedtypes = new type[] { typeof(string), typeof(int), typeof(decimal), typeof(double), typeof(bool), typeof(datetime), typeof(byte[]) }; if (supportedtypes.where(typ => typ == descriptor.parametertype).count() > 0) return new simplepostvariableparameterbinding(descriptor); } return null; } private object stringtotype(string stringvalue) { object value = null; if (stringvalue == null) value = null; else if (descriptor.parametertype == typeof(string)) value = stringvalue; else if (descriptor.parametertype == typeof(int)) value = int.parse(stringvalue, cultureinfo.currentculture); else if (descriptor.parametertype == typeof(int32)) value = int32.parse(stringvalue, cultureinfo.currentculture); else if (descriptor.parametertype == typeof(int64)) value = int64.parse(stringvalue, cultureinfo.currentculture); else if (descriptor.parametertype == typeof(decimal)) value = decimal.parse(stringvalue, cultureinfo.currentculture); else if (descriptor.parametertype == typeof(double)) value = double.parse(stringvalue, cultureinfo.currentculture); else if (descriptor.parametertype == typeof(datetime)) value = datetime.parse(stringvalue, cultureinfo.currentculture); else if (descriptor.parametertype == typeof(bool)) { value = false; if (stringvalue == "true" || stringvalue == "on" || stringvalue == "1") value = true; } else value = stringvalue; return value; } /// <summary> /// read , cache request body /// </summary> /// <param name="request"></param> /// <returns></returns> private namevaluecollection tryreadbody(httprequestmessage request) { object result = null; // try read out of cache first if (!request.properties.trygetvalue(multiplebodyparameters, out result)) { var contenttype = request.content.headers.contenttype; // read if there's content , it's form data if (contenttype == null || contenttype.mediatype != "application/x-www-form-urlencoded") { // nope no data result = null; } else { // parsing string firstname=hongmei&lastname=asdasd result = request.content.readasformdataasync().result; } request.properties.add(multiplebodyparameters, result); } return result namevaluecollection; } private struct asyncvoid { } } then in startup.cs invoke global configuration , insert before param binding rules, own rule (on first position in structure) invoking factory method hookupparameterbinding
globalconfiguration.configuration.parameterbindingrules.insert( 0, simplepostvariableparameterbinding.hookupparameterbinding ); now recompile application , check again page. controller not require send method signature request
test api description post api/test no documentation available. now trying our method, tried in blogpost
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <form> name: <input type="text" id="name" value="ggg" /> age: <input type="text" id="age" value="ddd" /> <input type="button" id="btnsend" value="send" /> </form> <script type="text/javascript"> $("#btnsend").click(function () { $.ajax({ url: "http://localhost:50931/api/test", type: "post", data: { name: $("#name").val(), age: $("#age").val() }, success: function(response) { alert(response) } }); }); </script> by clicking button, recieve alert saying smth, because `return "smth"
if open freibug console , track send via jquery, see
post http://localhost:50931/api/test 200 ok 2ms jquery-1.10.2.js (line 8720) headerspostresponsejsoncookies parametersapplication/x-www-form-urlencodeddo not sort age ddd name ggg as alternative can use simple json serializing, can make our method signature expect jobject
using newtonsoft.json.linq; public class testcontroller : apicontroller { [httppost] public string something(jobject obj) { return obj["name"] + " bla " + obj["age"]; } } if post against method, html above, recieve alert saying ddd bla ggg.
Comments
Post a Comment