WebAPI 2 Custom Model Binder is never Invoked - asp.net-web-api2

I am using latest bit of WebAPI 2. I am running into problem where default ModelBinder is not surfacing the posted value properly. I did verify that value is correctly posted back to the Server, i am able to retrieve that using Request Object. So decided to implement my own custom Model Binder. Now i am running into problem where this Custom Binder is never Invoked, only the Default Binder is invoked. what i am i missing ?
WebAPI Method
public IHttpActionResult PutOrg([ModelBinder(typeof(MyOrgModelBinder))] Org org)
{
}
Custom ModelBinder
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.ModelBinding;
using System.Web.Http.ValueProviders;
namespace SM4.Models
{
public class MyOrgModelBinder : IModelBinder
{
public bool BindModel(HttpActionContext controllerContext,
ModelBindingContext bindingContext)
{
var org = new Org
{
OrgCode_PK = request.Form.Get("OrgCode_PK"),
OrgHeadCode_FK = request.Form.Get("OrgHeadCode_FK"),
Code = request.Form.Get("Code"),
Name = "THIS is FROM BINDER",
Description = request.Form.Get("Description"),
Address1 = request.Form.Get("Address1"),
Address2 = request.Form.Get("Address2"),
CountryCode_FK = request.Form.Get("CountryCode_FK"),
StateCode_FK = request.Form.Get("StateCode_FK"),
CityCode_FK = request.Form.Get("CityCode_FK"),
ZIP = request.Form.Get("ZIP"),
RowStatusCode_FK = request.Form.Get("RowStatusCode_FK"),
EffectiveDate = DateTime.ParseExact(request.Form.Get("EffectiveDate"), "yyyy-MM-dd",
System.Globalization.CultureInfo.InvariantCulture),
TerminationDate = DateTime.ParseExact(request.Form.Get("TerminationDate"), "yyyy-MM-dd",
System.Globalization.CultureInfo.InvariantCulture),
};
bindingContext.Model = org;
return true;
}
}
}

Related

Return a File From ApplicationService Base Class

I'm trying to export data in SQL table called UploadedFileEntities into excel file I use angular in front-end and .NET core in Backend (ASP.Net Core boilerplate framework).
the problem is I can't return a file by Application class because of File is a class for Controller Base class,
So how could I return File from ApplicationService Base class?
Here is my code
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using OfficeOpenXml;
using PHC.Entities;
using PHC.EntityFrameworkCore;
using PHC.MySystemServices.MyApplicationServices.DTO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using IdentityModel.Client;
using Ninject.Activation;
using DocumentFormat.OpenXml.ExtendedProperties;
namespace PHC.MySystemServices.MyApplicationServices
{
public class MyApplicationAppService : AsyncCrudAppService<MyApplication, MyApplicationDto, int, PagedAndSortedResultRequestDto, MyApplicationDto>
{
private readonly IDbContextProvider<PHCDbContext> _dbContextProvider;
private PHCDbContext db => _dbContextProvider.GetDbContext();
private readonly IRepository<MyApplication,int> _repository;
private IHostingEnvironment _env;
public MyApplicationAppService(IDbContextProvider<PHCDbContext> dbContextProvider, IRepository<MyApplication, int> repository, IHostingEnvironment hostingEnvironment) :base(repository)
{
_repository = repository;
_dbContextProvider = dbContextProvider;
this._env = hostingEnvironment;
}
public async Task<IActionResult> ExportV2(CancellationToken cancellationToken)
{
// query data from database
await Task.Yield();
var list = db.UploadedFileEntities.ToList();
var stream = new MemoryStream();
ExcelPackage.LicenseContext = LicenseContext.NonCommercial; // this is important
using (var package = new ExcelPackage(stream))
{
var workSheet = package.Workbook.Worksheets.Add("Sheet1");
workSheet.Cells.LoadFromCollection(list, true);
package.Save();
}
stream.Position = 0;
string excelName = $"UserList-{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.xlsx";
//return File(stream, "application/octet-stream", excelName);
return new File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", excelName); //it doesn't work
}
}
if I return File Visual studio show me
non-invocable member 'File' cannot be used like a method
if I return new File Visual studio show me:
Cannot create an instance of the static class 'File'
The file method is derived from ControllerBase.File while you do not inherit it.
You could try FileStreamResult like
return new FileStreamResult(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = excelName
};

Consuming WCF service in objective C

I m new to iPhone programming.
What I want to do authenticate a user in iPhone using webservice. For instance
I Have a WCF webservice that I want to consume in my objective C code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Runtime.Serialization;
using MobileKpi.Business;
namespace MobileKpi.Services
{
[ServiceContract]
public interface IUploadData
{
[OperationContract]
[WebInvoke(UriTemplate = "UploadUserSessionData/", Method = "POST")]
string UploadUserSessionData(SessionXML pstrXML);
}
[DataContract(Namespace = "", Name = "UserLogin")]
public class UserLogin
{
string user = "";
string pass = "";
[DataMember(Name = "userName")]
public string userName
{
get { return user; }
set { user = value; }
}
[DataMember(Name = "password")]
public string password
{
get { return pass; }
set { pass = value; }
}
}
}
I want to access its two data members user and password . How can I do it in Objective C.
Any solutions Or Sample Code.
One place you could start is reviewing the code in the answer of this SO question. It shows how to send JSON but you could tweak it to work with XML instead. In your code, you don't show how you expect UserLogin to be sent to the service. You could add it as a parameter as follows:
[ServiceContract]
public interface IUploadData
{
[OperationContract]
[WebInvoke(UriTemplate = "UploadUserSessionData/", Method = "POST")]
string UploadUserSessionData(SessionXML pstrXML, UserLogin credentials);
}

DataContract Attributes not being sent in responses

I have had it where the name/namespace/other attributes show up when sending a request, but now they have disappeared and cant figure out for the life of me what changed... I am trying to utilize the WebApi project but the documentation seems limited.
WebServiceResource.cs :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel;
using System.ServiceModel.Web;
using wsDAL.EDataTypes;
using System.Data;
using System.IO;
using System.Text;
using System.Net.Http;
namespace wsDAL
{
[ServiceContract]
public class WebServiceResources
{
[WebGet(UriTemplate = "/GetNameValueTest/{name}/{value}")]
public NameValue GetNameValueTest(string name, string value)
{
NameValue nv = new NameValue("WS_" + name + "_WS", "WS_" + value + "_WS");
return nv;
}
}
}
GeneralResources.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.Data;
namespace wsDAL.EDataTypes
{
[DataContract(Name = "NameValueContract", Namespace = "http://fred.NameValue.com")]
public class NameValue
{
private string _name;
private string _value;
public NameValue()
{
_name = null;
_value = null;
}
public NameValue(string Name, string Value)
{
_name = Name;
_value = Value;
}
[DataMember(Name = "NameMember")]
public string Name { get { return _name; } set { _name = value; } }
[DataMember(Name = "ValueMember")]
public string Value { get { return _value; } set { _value = value; } }
}
}
Note I am using lightcore as an IOC container (kinda new to this stuff)
Was originally going of the post at http://blog.alexonasp.net/post/2011/04/15/Microsoft-Web-API-e28093-the-REST-is-done-by-WCF-(Part-1).aspx
but once I got to part six where he is returning HttpResponseMessage<Contact> from POSTs, it all started falling apart. client was looking for the namespace when returning xml but that was not part of the serialized response...
Global.asax.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using LightCore;
using Microsoft.ApplicationServer.Http.Description;
using Microsoft.ApplicationServer.Http.Activation;
....
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
ContainerBuilder builder = new ContainerBuilder();
builder.Register<IResourceFactory, LightCoreResourceFactory>();
IContainer container = builder.Build();
var configuration = HttpHostConfiguration.Create().SetResourceFactory((serviceType, instanceContext, request) => container.Resolve(serviceType), null);
RouteTable.Routes.MapServiceRoute<WebServiceResources>("ws", configuration);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
....
Ok, what it seems that I failed to realize, is that the name/namespace info gets serialized to the server, but not to the client.
Have you added a routing table record?
RouteTable.Routes.MapServiceRoute<WebServiceResources>("GetNameValueTest");
Updated answer on this... I was using a DataContractSerializer on the client which was adding the name/namespace info, while on the server I was using the default WebApi serialization which was not adding the info. Thanks for anyone who took time looking into this.

How to access custom attributes defined in WCF service using C#?

First question is, how can I get the type of an object stored in a variable? Generally we do:
Type t = typeof(ClassName); //if I know the class
but, how can I say something:
Type t = typeof(varClassName); //if the class name is stored in a variable
Second question, a broader picture is, I have a WCF service that contains a DataContract class say "MyClass" and I have defined a custom attribute called "MyAttribute" to it. There is one method say "GetDataUsingDataContract" with a parameter of type MyClass. Now on client, I invoke the webservice. I use MethodInfo and ParameterInfo classes to get the parameters of the method in question. But how can I access the attributes of the method parameter which is actually a class Myclass? Here is the code that I tried:
MyService.Service1Client client = new MyService.Service1Client();
Type t = typeof(MyService.Service1Client);
MethodInfo members = t.GetMethod("GetDataUsingDataContract");
ParameterInfo[] parameters = members.GetParameters();
foreach (var parameter in parameters)
{
MemberInfo mi = parameter.ParameterType; //Not sure if this the way
object[] attributes;
attributes = mi.GetCustomAttributes(true);
}
Above code doesn't retrieve me the custom attribute "MyAttribute". I tried the concept in the class that is defined in the same project and it works. Please HELP!
but, how can I say something:
Type t = typeof(varClassName); //if the class name is stored in a variable
Try
Type.GetType("varClassName", false, true);
As to your second question:
Above code doesn't retrieve me the
custom attribute "MyAttribute". I
tried the concept in the class that is
defined in the same project and it
works. Please HELP!
Just guessing, I'm not sure that attributes are exposed to the client, by default. I think its the same issue as an untrusted assembly. Some attributes are sensitive info. See this:
http://blogs.msdn.com/b/haibo_luo/archive/2006/02/21/536470.aspx
But you could try linking the service project types into your app by first referencing the service assembly in your client project, then going to your service reference -> "Configure Service Reference" and selecting "Reuse types in all referenced assemblies". I'm not sure this option will affect the service interface classes, but I use it often with my domain objects. Worth a try.
Type mi = parameter.ParameterType; //Not sure if this the way
object[] attributes;
attributes = mi.GetCustomAttributes(true);
Ensure your proxy class has knowledge on attributes
Hope this will help
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Reflection;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
StartService();
}
string url = "http://localhost:234/MyService/";
private void StartClient()
{
IMyService myService = ChannelFactory<IMyService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(url));
Type t = typeof(IMyService);
MethodInfo members = t.GetMethod("MyMethod");
ParameterInfo[] parameters = members.GetParameters();
foreach (var parameter in parameters)
{
Type mi = parameter.ParameterType;
object[] attributes;
attributes = mi.GetCustomAttributes(true);
}
}
private void StartService()
{
ServiceHost host = new ServiceHost(typeof(MyService), new Uri(url));
host.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "");
host.Open();
}
private void button1_Click(object sender, EventArgs e)
{
StartClient();
}
}
[AttributeUsage(AttributeTargets.Interface)]
public class MyAttrib : Attribute
{
}
[MyAttrib]
public interface IMyContract
{
string Name { get; set; }
}
[DataContract]
public class MyContract : IMyContract
{
[DataMember]
public string Name { get; set; }
}
[ServiceContract]
public interface IMyService
{
[OperationContract]
bool MyMethod(IMyContract dummy);
}
[ServiceBehavior(UseSynchronizationContext = false)]
public class MyService : IMyService
{
public bool MyMethod(IMyContract dummy)
{
return true;
}
}
}

Passing DTO's from a seperate Project to UI Layer WCF RIA services

I have a solution that I have designed with 5 layers.
They are:
UI/Presentation Layer
Service Layer
Business Logic Layer
Data Access Layer
DTO/Common Layer (IQUTECHDTO)
I want to pass the DTO to the UI. Below is the service layer that exposes a method GetVendors which I want to return the VendorDTO. This object will populate a drop down box.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using IQUTechDTO;
using IQUTECHDAL;
namespace BusinessApplication6.Web.Services
{
public class Foos
{
[Key]
public int FooId { get; set; }
public string Name { get; set; }
}
// TODO: Create methods containing your application logic.
[EnableClientAccess()]
public class BillService : DomainService
{
public IEnumerable<Foos> GetFoos()
{
return new List<Foos> { new Foos { FooId = 42, Name = "Fred" } };
}
[Query]
public IEnumerable<VendorDTO> GetVendors()
{
return new List<VendorDTO> { new VendorDTO { VendorID = 42 } };
}
}
}
On the UI .cs file when I try and create an object of type VendorDTO I cannot. I was however able to access the Foo object from the UI Layer.
The VendorDTO was marked as serialazble but it does however reside in a seperate project (IQUTECHDTO)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.ServiceModel.DomainServices;
using System.ServiceModel.Web;
namespace IQUTechDTO
{
public enum LoadStatus
{
Initialized = 0,
Ghost = 1,
Loaded = 2
}
[Serializable]
public class VendorDTO
{
/// <summary>
///DTO for the 'Vendor' object.
/// </summary>
public VendorDTO()
{
this.loadStatus = LoadStatus.Initialized;
}
///<summary>
/// Copy constructor
///</summary>
public VendorDTO(VendorDTO sourceDTO)
{
loadStatus = sourceDTO.loadStatus;
VendorID = sourceDTO.VendorID;
VendorName = sourceDTO.VendorName;
VendorAddress1 = sourceDTO.VendorAddress1;
VendorAddress2 = sourceDTO.VendorAddress2;
VendorCity = sourceDTO.VendorCity;
VendorState = sourceDTO.VendorState;
VendorEmail = sourceDTO.VendorEmail;
VendorPhone = sourceDTO.VendorPhone;
VendorPOC = sourceDTO.VendorPOC;
VendorRegion = sourceDTO.VendorRegion;
}
public LoadStatus loadStatus;
[Key]
public int VendorID { get; set; }
public string VendorName;
private string VendorAddress1;
private string VendorAddress2;
private string VendorEmail;
private string VendorPhone;
private string VendorCity;
private string VendorState;
private string VendorPOC;
private string VendorRegion;
}
}
Below is the UI Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using BusinessApplication6.Web.Services;
using System.ServiceModel.DomainServices.Client;
using BusinessApplication6.Web;
namespace BusinessApplication6.Views.BOM
{
public partial class BOMCRUD : Page
{
public BOMCRUD()
{
InitializeComponent();
LoadTree();
}
public void LoadTree()
{
BillContext newCon = new BillContext();
//This works
Foos fooobj = new Foos();
//This doesnt work
VendorDTO vendorobj = new VendorDTO();
}
// Executes when the user navigates to this page.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
}
}
Why will it not let me access this object.
Your help would be greatly appreciated.
Regards,
Tom
The UI class has doesn't have a reference to IQUTECHDTO like the Foos class does(in BusinessApplication6.Web).