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