Call Webapi with Dictionary<String, object> as parameter from ASP .NET MVC Application - asp.net-mvc

I have a WebApi defined as below
public ActionResult DoSomeAction([FromForm(Name = "file")] IFormFile dataFile,
Dictionary<string,object> collection)
{
//do something
}
I am trying to call this from my client as shown below,
using (var client = new HttpClient())
{
var api_Uri = Environment.GetEnvironmentVariable("API_URL");
client.BaseAddress = new Uri(api_Uri);
client.DefaultRequestHeaders.Clear();
//Define request data format
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Dictionary<string, object> data = new Dictionary<string, object>();
data.Add("a", "sasas");
data.Add("b", "sasas");
data.Add("", "sasas");
var inputSerialized = JsonSerializer.Serialize(data);
var stringContent = new StringContent(inputSerialized , Encoding.UTF8, "application/json");
var requestString = string.Format("api/DoSomeAction?selectedRule={0}", stringContent);
HttpResponseMessage Res = await client.PostAsync(requestString, multipartContent);
}
multipartContent is MultipartFormDataContent which contains File information.
The above code is not working. Some guidance would be appreciated.

I was able to solve this my implementing a custom IModelBinder.
I moved IFormFile and Dictionary to a class.
While creating the request as below ,
internal MultipartFormDataContent GetRequestParams(IFormFile FilePath)
{
MultipartFormDataContent multipartContent = GetFileContent(FilePath);
var dataExtractor = new DataExtractor();
var dictionaryData = dataExtractor.GetDictionary(); //This return Dictionary<string,object>
var serialisedData = JsonSerializer.Serialize(dictionaryData);
var stringContent = new StringContent(serialisedData, Encoding.UTF8, "application/json");
multipartContent.Add(stringContent, "MyCollection");
return multipartContent;
}
private MultipartFormDataContent GetFileContent(IFormFile FilePath)
{
byte[] data;
using (var br = new BinaryReader(FilePath.OpenReadStream()))
{
data = br.ReadBytes((int) FilePath.OpenReadStream().Length);
}
ByteArrayContent bytes = new ByteArrayContent(data);
MultipartFormDataContent multiContent = new MultipartFormDataContent();
multiContent.Add(bytes, "File", FilePath.FileName);
//Key is "File", bcos my property name in class is File. This should match
return multiContent;
}
Custom class containing the data
public class Input
{
public IFormFile File { get; set; }
[ModelBinder(BinderType = typeof(FormDataJsonBinder))]
public Dictionary<string,object> MyCollection{ get; set; }
}
Custom IModelBinder implementation
public class FormDataJsonBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var modelName = bindingContext.ModelName;
var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
if (valueProviderResult == ValueProviderResult.None)
{
return Task.CompletedTask;
}
bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);
var value = valueProviderResult.FirstValue;
if (string.IsNullOrEmpty(value))
{
return Task.CompletedTask;
}
try
{
var result = JsonSerializer.Deserialize(value, bindingContext.ModelType);
bindingContext.Result = ModelBindingResult.Success(result);
}
catch (Exception ex)
{
bindingContext.Result = ModelBindingResult.Failed();
}
return Task.CompletedTask;
}
}
}
Web Api Signature
public IActionResult ExecuteRule([FromForm] Input inputdata)
{
// Do something
}

Related

HttpClient is sending NULL in web Api in mvc5

HttpClient is sending null values to controller while post and my code is here please help me
....................
using (HttpClient client=new HttpClient())
{
var parameters = ConvertToDictionary(tc);
client.BaseAddress = new Uri($"http://localhost:9797/");
var json = JsonConvert.SerializeObject(tc);
var data = new StringContent(content: json,encoding: Encoding.UTF8,mediaType: "application/json");
var response = client.PostAsync(api_url, data).GetAwaiter().GetResult();
var k = JsonConvert.DeserializeObject<Api>(response.Content.ReadAsStringAsync().GetAwaiter().GetResult());
}
Thanks in advance
Try to use # insted of $ in client.BaseAddress. And check if tc object is not null.
I used Your code like this:
class Program
{
static void Main(string[] args)
{
using (HttpClient client=new HttpClient())
{
client.BaseAddress = new Uri(#"http://localhost:61737/api/presidents");
var json = JsonConvert.SerializeObject(new { name = "name", value = "value" });
var data = new StringContent(content: json,encoding: Encoding.UTF8,mediaType: "application/json");
var response = client.PostAsync(#"http://localhost:61737/api/presidents/post", data).GetAwaiter().GetResult();
var k = (response.Content.ReadAsStringAsync().GetAwaiter().GetResult());
}
}
}
And controller looks like this:
[RoutePrefix("api/presidents")]
public class PresidentsController : ApiController
{
public class oooo
{
public string Name { get; set; }
public string Value { get; set; }
}
[Route("post")]
public IHttpActionResult Post(oooo o)
{
return Ok(o);
}
}
and everything is working.

Object is null when passed to web api in c#

I have created web api in asp.net mvc. What I want is to call that post method in web api from another project (website) in asp.net.
Here is my Class Vendor
[ModelBinder(typeof(VendorModelBinder))]
public class Vendor
{
public string VenName { get; set; }
public string VenCompany { get; set; }
}
Here is VendorModelBinder
public class VendorModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(Vendor))
{
return false;
}
Vendor result = JsonConvert.DeserializeObject<Vendor>
(actionContext.Request.Content.ReadAsStringAsync().Result);
bindingContext.Model = result;
return true;
}
Here is my VendorController
public class VendorController : ApiController
{
// POST: api/Vendor/5
[HttpPost]
[Route("")]
public HttpResponseMessage Post([ModelBinder]Vendor Ven)
{
SqlConnection con = new SqlConnection(" Data Source = DELL; Initial Catalog = EVENT; Integrated Security = True");
SqlCommand com = new SqlCommand("[dbo].[InsVendor]", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#user", Ven.VenName);
com.Parameters.AddWithValue("#compnay", Ven.VenCompany);
con.Open();
int i = com.ExecuteNonQuery();
con.Close();
HttpResponseMessage message = Request.CreateResponse(HttpStatusCode.OK);
message.Content = content;
return message;
}
}
Here I am calling the post method in web api
static async Task<Uri> AddVendorAsync(AllVendor Ven)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:56908/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
StringContent content = new StringContent(JsonConvert.SerializeObject(Ven), Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync("api/Vendor", content);
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
Console.WriteLine("Success");
}
// return URI of the created resource.
return response.Headers.Location;
}
}
Is the above procedure correct?
Because I am getting the null object at the Vendor Controller (Ven.VenName)
Kindly, help me on this one.
Thanks.

Call WCF Restful POST Method in MVC 5

I have to create simple WCF web service with GET and POST. See bellow source code
public interface ISample
{
[OperationContract]
[WebGet(UriTemplate = "/GetDEPT", RequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json)]
Task<IEnumerable<DEPT>> GetDEPT();
[OperationContract]
[WebInvoke(UriTemplate = "UpdateDEPT?Id={Id}&StatusId={StatusId}", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
Task<bool> UpdateDEPT(List<DEPT> DEPT, string Id, string StatusId);
}
ISample interface Implementation : Sample
public class Sample: ISample
{
public async Task<IEnumerable<DEPTt>> GetDEPT()
{
return await DEPTBO.GetDEPT();
}
public async Task<bool> UpdateDEPT(List<DEPTt> DEPT, string Id, string StatusId)
{
return await DEPTBO.UpdateDEPTAsync(Id, DEPT, StatusId);
}
}
How to call this WCF Restful service in MVC 5?
Please help me Service integration in MVC Application
Now i found the solution for my question.
I have create class for proxy
namespace WCF.WCFService
{
public static class WebService<T> where T : class
{
public static string appSettings = ConfigurationManager.AppSettings["ServiceURL"];
public static IEnumerable<T> GetDataFromService(string Method, string param = "")
{
var client = new WebClient();
var data = client.DownloadData(appSettings + Method + param);
var stream = new System.IO.MemoryStream(data);
var obj = new DataContractJsonSerializer(typeof(IEnumerable<T>));
var result = obj.ReadObject(stream);
IEnumerable<T> Ts = (IEnumerable<T>)result;
return Ts;
}
}
public static class WebServiceUpdate
{
public static string appSettings = ConfigurationManager.AppSettings["ServiceURL"];
public static bool GetDataFromService_Update(string Method, List<CNHDataModel.CustomEntities.Port> portData, string param = "")
{
bool _res = false;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<CNHDataModel.CustomEntities.Port>));
MemoryStream mem = new MemoryStream();
serializer.WriteObject(mem, portData);
string data =
Encoding.UTF8.GetString(mem.ToArray(), 0, (int)mem.Length);
WebClient webClient = new WebClient();
webClient.Headers["Content-type"] = "application/json";
webClient.Encoding = Encoding.UTF8;
webClient.UploadString(appSettings + Method + param, "POST", data);
_res = true;
bool Ts = (bool)_res;
return Ts;
}
}
}
Bellow, call the service proxy from controller
public class DEPTController : Controller
{
[ActionName("DEPTView")]
public ActionResult DEPTViewAsync()
{
try
{
IEnumerable<DEPT> DEPT = CNHService.WebService<DEPT>.GetDataFromService("GetDEPT");
if (port == null)
{
return HttpNotFound();
}
IEnumerable<Status> Status = CNHService.WebService<Status>.GetDataFromService("GetStatusAsync");
if (port == null || Status == null)
{
return HttpNotFound();
}
}
catch (Exception ex)
{
}
return View();
}
[HttpPost]
[ActionName("DEPTView")]
public ActionResult DEPTViewAsync([Bind(Include = "id,Statusid")] DEPT DEPTMENT)
{
try
{
List<DEPT> objDEPT = Session["DEPTItems"] as List<DEPT>;
List<DEPTStatus> objStatus = Session["DEPTIStatus"] as List<PortStatus>;
ViewBag.DEPTList = new SelectList(objDEPTt, "id", "Name");
ViewBag.DEPTStatusList = new SelectList(objStatus, "id", "Name");
if (ModelState.IsValid)
{
WebServiceUpdate.GetDataFromService_Update("UpdateDEPT", objDEPT, "?Id=" + DEPTMENT.Id + "&StatusId=" + DEPTMENT.Statusid);
setting.Message = true;
}
else
{
return View(setting);
}
}
catch (Exception ex)
{
}
return View(setting);
}
}
I hope this code help to WCF Restful service integration in MVC 5

Intercept JsonResult and wrap it (as string)

I have a action that return JsonResult.
I want to intercept the JsonResult return and wrap it with string.
Something like:
public class JsonProxyAttribute : FilterAttribute
{
void OnActionExecuting(ExceptionContext filterContext)
{
var res = filterContext.Result as string;
if (res != null)
{
filterContext.Result = "func("+filterContext.Result+")";
}
}
}
So the ajax call will get this:
func({"MyContent":"content"})
instead of this:
{"MyContent":"content"}
What you need is to create a new ActionResult that will extend JsonResult and represent JSONP
public class JsonpResult : JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = ContentType ?? "application/x-javascript";
response.ContentEncoding = ContentEncoding ?? System.Text.Encoding.UTF8;
if (Data != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
string ser = serializer.Serialize(Data);
response.Write("func(" + ser + ");");
}
}
}
Now if you want to intercept regular JSON results, your ActionFilter would look like this.
public class JsonProxyAttribute : FilterAttribute
{
void OnActionExecuting(ExceptionContext filterContext)
{
var res = filterContext.Result as JsonResult;
if (res != null)
{
filterContext.Result = new JsonpResult
{
ContentEncoding = res.ContentEncoding,
ContentType = res.ContentType,
Data = res.Data,
JsonRequestBehavior = res.JsonRequestBehavior
};
}
}
}
Or you can use JSONP directly in your controllers
public ActionResult Jsonp()
{
var model = new List<string> { "one", "two" };
return new JsonpResult
{
Data = model,
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}

AuthorizationState cannot be serialized because it does not have a parameterless constructor

The implementation for authorization state in the source indicates that the authorization state should be serializable, but when I try to serialize the authorization state to store in my authentication ticket, I get an error saying that the implementation needs a parameterless constructor.
Snipped from the referenced source:
[Serializable]
public class AuthorizationState : IAuthorizationState {
...
public AuthorizationState(IEnumerable<string> scopes = null) {
How I'm getting the state:
var Authorization = Client.ProcessUserAuthorization();
How I'm trying to serialize the state:
public string Serialize(IAuthorizationState objectInstance)
{
var serializer = new XmlSerializer(objectInstance.GetType());
var sb = new StringBuilder();
using (TextWriter writer = new StringWriter(sb))
{
serializer.Serialize(writer, objectInstance);
}
return sb.ToString();
}
I ran a quick console app
class Program
{
static void Main(string[] args)
{
var can = new CanSerialize();
var cant = new CantSerialize();
var ser1 = can.Serialize();
var ser2 = cant.Serialize();
}
}
[Serializable]
public class CantSerialize
{
public int id { get; set; }
public CantSerialize(int ID = 1)
{
id = ID;
}
public string Serialize()
{
var serializer = new XmlSerializer(this.GetType());
var sb = new StringBuilder();
using (TextWriter writer = new StringWriter(sb))
{
serializer.Serialize(writer, this);
}
return sb.ToString();
}
}
[Serializable]
public class CanSerialize
{
public int id { get; set; }
private CanSerialize()
{
id = 1;
}
public CanSerialize(int ID = 1)
{
id = ID;
}
public string Serialize()
{
var serializer = new XmlSerializer(this.GetType());
var sb = new StringBuilder();
using (TextWriter writer = new StringWriter(sb))
{
serializer.Serialize(writer, this);
}
return sb.ToString();
}
}
Can the implementation have a default parameterless constructor? As the sample shows, it can be private if there is concern about having a public ctor.
In the meantime, I'm going to create a data transfer object to ferry the information back and forth between my authorization token and the state.
EDIT:
I've found that the JSON.net conversion works well:
var a = JsonConvert.SerializeObject(Authorization);
var b = JsonConvert.DeserializeObject(a, typeof(AuthorizationState));
I've found that the JSON.net conversion works well:
var a = JsonConvert.SerializeObject(Authorization);
var b = JsonConvert.DeserializeObject(a, typeof(AuthorizationState));

Resources