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
Related
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
}
I'm looking to add records to an Umbraco v8 form. I know I need the form guid. Is this how I'd do it? Something like this?
public void PostFormData()
{
Guid FormGuid = new Guid("8494a8f0-94da-490e-bd61-7e658c226142");
var form = _formService.Get(FormGuid);
//place for field data into fieldDic
var fieldDic = new Dictionary<Guid, RecordField>();
var firstName = form.AllFields.First(f => f.Alias == "firstName");
var firstNameRecord = new RecordField(firstName);
firstNameRecord.Values = new List<object>() { "Mad Max" };
fieldDic.Add(firstName.Id, firstNameRecord);
var record = new Record()
{
Created = DateTime.Now,
Form = form.Id,
RecordFields = fieldDic,
State = FormState.Submitted,
};
record.RecordData = record.GenerateRecordDataAsJson();
_recordStorage.InsertRecord(record, form);
}
Here's how I do it. Note, I'm hard-coding the Record.UmbracoPageId to -1 while you might want to actually pass in the correct page ID.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Umbraco.Core;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Forms.Core.Data.Storage;
using Umbraco.Forms.Core.Models;
using Umbraco.Forms.Core.Persistence.Dtos;
using Umbraco.Forms.Core.Services;
namespace myProject.Services
{
public class FormServiceComposer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<IFormService, FormService>(Lifetime.Request);
}
}
public interface IFormService
{
void InsertFormData(Guid formGuid, object formModel, string ipAddress);
}
public class FormService : IFormService
{
private readonly ILogger _logger;
private readonly Umbraco.Forms.Core.Services.IFormService _formService;
private readonly IRecordStorage _recordStorage;
private readonly IRecordFieldStorage _recordFieldStorage;
private readonly IWorkflowService _workflowService;
public FormService(ILogger logger, Umbraco.Forms.Core.Services.IFormService formService, IRecordStorage recordStorage, IRecordFieldStorage recordFieldStorage, IWorkflowService workflowService)
{
_logger = logger;
_formService = formService;
_recordStorage = recordStorage;
_recordFieldStorage = recordFieldStorage;
_workflowService = workflowService;
}
#region IFormService
public void InsertFormData(Guid formGuid, object formModel, string ipAddress)
{
try
{
Form form = _formService.GetForm(formGuid);
Record record = new Record();
foreach (Field field in form.AllFields)
{
string caption = CleanCaption(field.Caption);
if (formModel.GetType().GetProperty(caption) == null) continue;
var propertyValue = formModel.GetType().GetProperty(caption).GetValue(formModel, null);
if (propertyValue != null)
{
List<object> values = ExtractValues(propertyValue);
RecordField recordField = new RecordField
{
Alias = field.Alias,
FieldId = field.Id,
Field = field,
Key = Guid.NewGuid(),
Record = record.Id,
Values = values
};
_recordFieldStorage.InsertRecordField(recordField);
record.RecordFields.Add(recordField.Key, recordField);
}
}
record.Form = formGuid;
record.IP = ipAddress;
record.UmbracoPageId = -1;
record.State = Umbraco.Forms.Core.Enums.FormState.Approved;
record.RecordData = record.GenerateRecordDataAsJson();
_recordStorage.InsertRecord(record, form);
_recordStorage.DisposeIfDisposable();
}
catch (Exception ex)
{
_logger.Error<FormService>(ex, "Failed inserting Umbraco Forms data for {formGuid}");
}
}
#endregion IFormService
#region Private
private string CleanCaption(string caption)
{
Regex rgx = new Regex("[^a-zA-Z0-9 -]");
return rgx.Replace(caption.Trim().Replace(" ", ""), "");
}
private List<object> ExtractValues(object propertyValue)
{
List<object> result = new List<object>();
if (propertyValue is string == false && propertyValue.GetType().GetGenericTypeDefinition() == typeof(List<>))
{
IEnumerable<object> _propertyValue = (IEnumerable<object>)propertyValue;
if (_propertyValue.Any())
{
if (_propertyValue.First().GetType().GetProperties().Count() > 1)
{
JArray _properties = JArray.Parse(JsonConvert.SerializeObject(propertyValue));
foreach (JToken item in _properties)
{
string _value = string.Empty;
foreach (var _property in _propertyValue.First().GetType().GetProperties())
{
string _key = _property.Name;
_value = _value + (_value == "" ? "" : " - ") + item[_key].ToString();
}
result.Add(_value);
}
}
else
{
string _key = _propertyValue.First().GetType().GetProperties().First().Name;
JArray _properties = JArray.Parse(JsonConvert.SerializeObject(propertyValue));
foreach (JToken item in _properties)
{
result.Add(item[_key].ToString());
}
}
}
}
else
{
result.Add(propertyValue);
}
return result;
}
#endregion Private
}
}
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
};
}
I combine my tables to Result. İt works with no problem.
public ActionResult Index()
{
var Result = new Modeller
{
KISALTMALAR = context.KISALTMALAR.ToList(),
FirmaListesiGetir = context.SP_FIRMA_LISTESI_GETIR().ToList(),
};
return View(Result );
}
However, when using multiple actions, i have to write the above code every time.
For instance:
public ActionResult Customer()
{
var Result = new Modeller
{
KISALTMALAR = context.KISALTMALAR.ToList(),
FirmaListesiGetir = context.SP_FIRMA_LISTESI_GETIR().ToList(),
};
return View(Result );
}
public ActionResult Product()
{
var Result = new Modeller
{
KISALTMALAR = context.KISALTMALAR.ToList(),
FirmaListesiGetir = context.SP_FIRMA_LISTESI_GETIR().ToList(),
};
return View(Result );
}
İ have to combine my tables in every actionresult.
How can i write only one time and use my Result everywhere ?
You may do as follows. I always use this approach:
public Modeller GetResult()
{
var result = new Modeller
{
KISALTMALAR = context.KISALTMALAR.ToList(),
FirmaListesiGetir = context.SP_FIRMA_LISTESI_GETIR().ToList(),
};
return result;
}
public ActionResult Customer()
{
var Result = GetResult();
return View(Result);
}
public ActionResult Product()
{
var Result = GetResult();
return View(Result);
}
One option is to just reference a shared class/service. For example:
public class YourService
{
public static Modeller GetCombinedTables()
{
return new Modeller
{
KISALTMALAR = context.KISALTMALAR.ToList(),
FirmaListesiGetir = context.SP_FIRMA_LISTESI_GETIR().ToList()
};
}
}
Then, in your action you can just call that method:
public ActionResult Customer()
{
var Result = YourService.GetCombinedTables();
return View(Result);
}
You can also create the Result variable at controller level, so that way you don't have to assign it for every action.
Here's the setup:
I have some MVC Controllers that are intended to be consumed by jQuery ajax requests. A normal request would seem somewhat like this:
$.ajax("/Solicitor/AddSolicitorToApplication", {
data: putData,
type: "POST", contentType: "application/json",
success: function (result) {
//My success callback
}
}
});
My controller looks like this:
[HttpPost]
public ActionResult InsertLoanApplication(MortgageLoanApplicationViewModel vm)
{
var mortgageLoanDTO = vm.MapToDTO();
return Json(_mortgageLoanService.UpdateMortgageLoanApplication(mortgageLoanDTO), JsonRequestBehavior.DenyGet);
}
This works perfectly fine with most objects passed to the controller, except that in this specific case one of the properties of the object being passed needs to be deserialized in a specific way.
I've added a JsonConverter that I've used previously with the MVC4 Web API, but in this case I need to apply it to regular mvc controllers.
I tried registering the JsonConverter in my global.asax like this:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new GrizlyStringConverter());
But so far haven't been able to deserialize the object.
You should replace the built-in JsonValueProviderFactory class with a custom one if you want to use Json.NET when binding JSON requests to view models.
You could write one as shown in this gist:
public sealed class JsonDotNetValueProviderFactory : ValueProviderFactory
{
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
{
return null;
}
using (var reader = new StreamReader(controllerContext.HttpContext.Request.InputStream))
{
var bodyText = reader.ReadToEnd();
return String.IsNullOrEmpty(bodyText)
? null :
new DictionaryValueProvider<object>(
JsonConvert.DeserializeObject<ExpandoObject>(
bodyText,
new ExpandoObjectConverter()
),
CultureInfo.CurrentCulture
);
}
}
}
and then replace the built-in with your custom one in Application_Start:
ValueProviderFactories.Factories.Remove(
ValueProviderFactories
.Factories
.OfType<JsonValueProviderFactory>()
.FirstOrDefault()
);
ValueProviderFactories.Factories.Add(new JsonDotNetValueProviderFactory());
That's it. Now you are using Json.Net instead of the JavaScriptSerializer for the incoming JSON requests.
The modified version:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace MvcJsonNetTests.Utils
{
public class JsonNetValueProviderFactory : ValueProviderFactory
{
public JsonNetValueProviderFactory()
{
Settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Error,
Converters = { new ExpandoObjectConverter() }
};
}
public JsonSerializerSettings Settings { get; set; }
public override IValueProvider GetValueProvider(ControllerContext controllerContext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (controllerContext.HttpContext == null ||
controllerContext.HttpContext.Request == null ||
controllerContext.HttpContext.Request.ContentType == null)
{
return null;
}
if (!controllerContext.HttpContext.Request.ContentType.StartsWith(
"application/json", StringComparison.OrdinalIgnoreCase))
{
return null;
}
if (!controllerContext.HttpContext.Request.IsAjaxRequest())
{
return null;
}
using (var streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream))
{
using (var jsonReader = new JsonTextReader(streamReader))
{
if (!jsonReader.Read())
return null;
var jsonSerializer = JsonSerializer.Create(this.Settings);
Object jsonObject;
switch (jsonReader.TokenType)
{
case JsonToken.StartArray:
jsonObject = jsonSerializer.Deserialize<List<ExpandoObject>>(jsonReader);
break;
default:
jsonObject = jsonSerializer.Deserialize<ExpandoObject>(jsonReader);
break;
}
var backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
addToBackingStore(backingStore, String.Empty, jsonObject);
return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture);
}
}
}
private static void addToBackingStore(IDictionary<string, object> backingStore, string prefix, object value)
{
var dictionary = value as IDictionary<string, object>;
if (dictionary != null)
{
foreach (var entry in dictionary)
{
addToBackingStore(backingStore, makePropertyKey(prefix, entry.Key), entry.Value);
}
return;
}
var list = value as IList;
if (list != null)
{
for (var index = 0; index < list.Count; index++)
{
addToBackingStore(backingStore, makeArrayKey(prefix, index), list[index]);
}
return;
}
backingStore[prefix] = value;
}
private static string makeArrayKey(string prefix, int index)
{
return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]";
}
private static string makePropertyKey(string prefix, string propertyName)
{
return (string.IsNullOrWhiteSpace(prefix)) ? propertyName : prefix + "." + propertyName;
}
}
}
Also to register it at the right index:
public static void RegisterFactory()
{
var defaultJsonFactory = ValueProviderFactories.Factories
.OfType<JsonValueProviderFactory>().FirstOrDefault();
var index = ValueProviderFactories.Factories.IndexOf(defaultJsonFactory);
ValueProviderFactories.Factories.Remove(defaultJsonFactory);
ValueProviderFactories.Factories.Insert(index, new JsonNetValueProviderFactory());
}