DataContract Attributes not being sent in responses - wcf

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.

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

Can we use Microsoft.AspNet.WebApi.Client from an ASP.NET Core application?

We want to be able to use the package Microsoft.AspNet.WebApi.Client from our ASP.NET Core MVC web application to make an HTTP call to an outside system. It does work but I couldn't find the corresponding source code in .NET core (github). Is it okay to use this library from the ASP.NET road map point of view? Will it be supported in ASP.NET Core going forward? Most importantly, will this package be supported in non-Windows platforms, as part of ASP.NET Core/.NET Core?
You can try what I did for a REST Client. I found that the assembly you have mentioned in it's latest version does not work in the recently released ASP.Net Core 1.0. Instead of "Microsoft.AspNet.WebApi.Client", use "System.Net.Http".
Then where you would have built an Http POST request like this:
using AvailabilityPricingClient.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AvailabilityPricingClient.Core.Model;
using System.Net.Http;
using System.Net.Http.Headers;
namespace AvailabilityPricingClient.Client
{
public class ProductAvailabilityPricing : IProductAvailabilityPricing
{
private HttpClient _client;
public ProductAvailabilityPricing(string apiUrl)
{
_client = new HttpClient();
_client.BaseAddress = new Uri(apiUrl);
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public void Dispose()
{
_client.Dispose();
}
public async Task<IEnumerable<Availablity>> GetAvailabilityBySkuList(IEnumerable<string> skuList)
{
HttpResponseMessage response = _client.PostAsJsonAsync("/api/availabilityBySkuList", skuList).Result;
if (response.IsSuccessStatusCode)
{
var avail = await response.Content.ReadAsAsync<IEnumerable<Availablity>>();
return avail;
}
return null;
}
}
}
You will now build like this:
using AvailabilityPricingClient.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AvailabilityPricingClient.Core.Model;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json;
namespace AvailabilityPricingClient.Client
{
public class ProductAvailabilityPricing : IProductAvailabilityPricing
{
private HttpClient _client;
public ProductAvailabilityPricing(string apiUrl)
{
_client = new HttpClient();
_client.BaseAddress = new Uri(apiUrl);
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
public void Dispose()
{
_client.Dispose();
}
public async Task<IEnumerable<Availablity>> GetAvailabilityBySkuList(IEnumerable<string> skuList)
{
var output = JsonConvert.SerializeObject(skuList);
HttpContent contentPost = new StringContent(output, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = _client.PostAsync("/api/availabilityBySkuList", contentPost).Result;
if (response.IsSuccessStatusCode)
{
var avail = await response.Content.ReadAsStringAsync()
.ContinueWith<IEnumerable<Availablity>>(postTask =>
{
return JsonConvert.DeserializeObject<IEnumerable<Availablity>>(postTask.Result);
});
return avail;
}
return null;
}
}
}
This way you interface does not change only the body of your request code changes.
This is working for me....Good luck....

WebAPI 2 Custom Model Binder is never Invoked

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

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

WCF Relocation of DataContracts

This is a fully functional WCF Hello World program. I.e. I am able to run this program without any Exception.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace DataContractsNamespace
{
[DataContract]
public class AccountInfo
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
namespace Clients
{
public class BankProxy : ServiceContractsNamespace.IBank
{
ServiceContractsNamespace.IBank channel;
public BankProxy()
{
channel = ChannelFactory<ServiceContractsNamespace.IBank>.CreateChannel(new BasicHttpBinding(), new EndpointAddress("http://localhost:8000/Services/BankService"));
}
public decimal GetAcccountBalance(string AcctNo)
{
return channel.GetAcccountBalance(AcctNo);
}
public DataContractsNamespace.AccountInfo GetAccountInfo(string AcctNo)
{
return channel.GetAccountInfo(AcctNo);
}
}
}
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Text;
namespace ServiceContractsNamespace
{
[ServiceContract]
public interface IBank
{
[OperationContract]
decimal GetAcccountBalance(string AcctNo);
[OperationContract]
DataContractsNamespace.AccountInfo GetAccountInfo(string AcctNo);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Clients
{
class Program
{
static void Main(string[] args)
{
BankProxy prox = new BankProxy();
Console.WriteLine("Hit enter to invoke the service call. Type exit then enter to close");
while (Console.ReadLine() != "exit")
{
string balance = prox.GetAcccountBalance("1234").ToString("c");
DataContractsNamespace.AccountInfo ai = prox.GetAccountInfo("1234");
Console.WriteLine("{0} {1} your account balance is {2}.", ai.FirstName, ai.LastName, balance);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Hosts
{
public class BankService : ServiceContractsNamespace.IBank
{
public decimal GetAcccountBalance(string AcctNo)
{
return 1.37m;
}
public DataContractsNamespace.AccountInfo GetAccountInfo(string AcctNo)
{
DataContractsNamespace.AccountInfo ai = new DataContractsNamespace.AccountInfo();
ai.FirstName = "Paul";
ai.LastName = "Johansen";
return ai;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
namespace Hosts
{
class Program
{
static void Main(string[] args)
{
ServiceHost servHo = new ServiceHost(typeof(BankService), new Uri("http://localhost:8000/Services"));
servHo.AddServiceEndpoint(typeof(ServiceContractsNamespace.IBank), new BasicHttpBinding(), "BankService");
servHo.Open();
Console.WriteLine("This service is open for business. Hit Enter to close.");
Console.ReadLine();
servHo.Close();
}
}
}
As you can see, AccountInfo - Data contract is shared by both Client and Host.
I need to keep data contract only to Host/Service side.
Clients should only see interfaces of DataContracts (like IAccountInfo).
How should I modify my program to introduce IAccountInfo?
It sounds like you want to return an interface instead of a class. I'm not exactly sure why you are not content to return AccountInfo. However, you should be able to do this but you will need to use a KnownType or perhaps ServiceKnownType to make it work.
Alternately, if you are working in a fully .NET environment you can use the NetDataContractSerializer instead of the DataContractSerializer.
For reference and examples you can check out:
http://nirajrules.wordpress.com/2009/08/26/wcf-serializers-xmlserializer-vs-datacontratserializer-vs-netdatacontractserializer/
http://www.pluralsight.com/community/blogs/aaron/archive/2006/04/21/22284.aspx
http://weblogs.asp.net/avnerk/archive/2006/07/31/WCF-Serialization-part-1_3A00_-Interfaces_2C00_-Base-classes-and-the-NetDataContractFormatSerializer.aspx
http://www.thoughtshapes.com/WCF/ExampleTwo.htm
And what should IBank.GetAccountInfo return to client if you don't want to share AccountInfo? create 2 classes make the first datacontract the second not, and where you want to share use the first one, where not, the second one