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 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.
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.
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
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
};
}
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));