I have a WCF Data Service running that is exposing an EDM. There are several properties I needed on the client side, that the database doesn't need to know about. After setting all that up I got to testing the SaveContext method and get this error on the server "Error processing request stream. The property name 'CanDelete' specified for type 'DataModels.Customer' is not valid."
Is there a way to tell WCF Data Services on the client side to ignore this property? Or should I move to RIA Serivces? I've read that setting the property to internal will do this, but I need the property for binding and I have the client UI code in a different project (de-coupling my SL applications from my data service).
on the client I have:
public partial class Customer
{
private bool canDelete;
/// <summary>
/// Gets or sets a value indicating whether this instance can be deleted.
/// </summary>
/// <value>
/// <c>true</c> if this instance can delete; otherwise, <c>false</c>.
private bool canDelete;
/// <summary>
/// Gets or sets a value indicating whether this instance can be deleted.
/// </summary>
/// <value>
/// <c>true</c> if this instance can delete; otherwise, <c>false</c>.
/// </value>
public bool CanDelete
{
get
{
return this.canDelete;
}
set
{
if (this.canDelete != value)
{
this.canDelete = value;
this.OnPropertyChanged("CanDelete");
}
}
}
}
I had the exact same problem and adapted some code below from
extending partial designer classes
It simply involves hooking the WritingEntity Event inside a partial class of the Context.
I added my own attribute (IgnorePropertyAttribute) so I could attach it to other properties.
Would of course be nice if the attribute wasnt inserted in the first place but this worked for me
public sealed class IgnorePropertyAttribute : Attribute
{
}
...
partial void OnContextCreated()
{
this.WritingEntity += MyDataContext_WritingEntity;
}
private void MyDataContext_WritingEntity(object sender, System.Data.Services.Client.ReadingWritingEntityEventArgs e)
{
//
foreach (XElement node in e.Data.Elements())
{
if (node != null && node.Name.LocalName == "content")
{
foreach (XElement el in node.Elements())
{
if (el.Name.LocalName == "properties")
{
foreach (XElement prop in el.Elements())
{
if(e.Entity.GetType().GetProperty(prop.Name.LocalName).GetCustomAttributes(typeof(IgnorePropertyAttribute), true).Length > 0)
{
prop.Remove();
}
}
}
}
}
}
}
Related
When i am testing my WCF web service through "WcfTestClient", it is showing
"this operation is not supported in wcf test client because it uses type VINDescription"
Where VINDescriptionis a DataContract, which is consist of datamembers of type :
"int, string, ArrayList"
It seems WCF web service is not supporting ArrayList?
Please suggest how can i fix this?
Here is a code snippet of DataContract :
[DataContract]
public class VINDescription
{
#region Private Members
private int _cylinders = 0;
private string _msrp = string.Empty;
private ArrayList _interior = new ArrayList();
private string[][] _showOptionalEquipment = new string[][] { };
#endregion
#region Public Data Members
/// <summary>
/// Stores the number of cylinders of a decoded vehicle.
/// </summary>
[DataMember]
public int Cylinders
{
get
{
return _cylinders;
}
set
{
_cylinders = value;
}
}
/// <summary>
/// Stores the MSRP cost of a decoded vehicle.
/// </summary>
[DataMember]
public string MSRP
{
get
{
return _msrp;
}
set
{
_msrp = value;
}
}
/// <summary>
/// Stores the interior values of a decoded vehicle.
/// </summary>
[DataMember]
public ArrayList Interior
{
get
{
_interior.Sort();
return _interior;
}
set
{
_interior = value;
}
}
/// <summary>
/// To store the data for show optional equipments.
/// </summary>
[DataMember]
public string[][] ShowOptionalEquipment
{
get
{
return _showOptionalEquipment;
}
set
{
_showOptionalEquipment = value;
}
}
The way I understand it, WCF actually supports your data contract, but the WCF Test Client tool does not support everything that WCF itself supports, hence the error. Not sure if it's because of ArrayList, string[][], or something else, but in any case it seems to be a tool limitation, not a framework limitation.
I'm trying to inject dependencies via Spring.NET.
First I created a custom DependencyResolver:
public class SignalRSpringNetDependencyResolver : DefaultDependencyResolver
{
private IApplicationContext _context;
public SignalRSpringNetDependencyResolver(IApplicationContext context)
{
_context = context;
}
/// <summary>
/// Gets the application context.
/// </summary>
/// <value>The application context.</value>
public IApplicationContext ApplicationContext
{
get
{
if (_context == null || _context.Name != ApplicationContextName)
{
if (string.IsNullOrEmpty(ApplicationContextName))
{
_context = ContextRegistry.GetContext();
}
else
{
_context = ContextRegistry.GetContext(ApplicationContextName);
}
}
return _context;
}
}
/// <summary>
/// Gets or sets the name of the application context.
/// </summary>
/// <remarks>
/// Defaults to using the root (default) Application Context.
/// </remarks>
/// <value>The name of the application context.</value>
public static string ApplicationContextName { get; set; }
/// <summary>
/// Resolves singly registered services that support arbitrary object creation.
/// </summary>
/// <param name="serviceType">The type of the requested service or object.</param>
/// <returns>The requested service or object.</returns>
public override object GetService(Type serviceType)
{
System.Diagnostics.Debug.WriteLine(serviceType.FullName);
if (serviceType != null && !serviceType.IsAbstract && !serviceType.IsInterface && serviceType.IsClass)
{
var services = ApplicationContext.GetObjectsOfType(serviceType).GetEnumerator();
services.MoveNext();
try
{
return services.Value;
}
catch (InvalidOperationException)
{
return null;
}
}
else
{
return base.GetService(serviceType);
}
}
/// <summary>
/// Resolves multiply registered services.
/// </summary>
/// <param name="serviceType">The type of the requested services.</param>
/// <returns>The requested services.</returns>
public override IEnumerable<object> GetServices(Type serviceType)
{
var services = ApplicationContext.GetObjectsOfType(serviceType).Cast<object>();
services.Concat(base.GetServices(serviceType));
return services;
}
Note that i escape interfaces and abstract classes so that I will get the default implementations of SignalR from the base DefaultDependencyResolver
and here I assigned the resolver using WebActivator:
public static void PostStart()
{
// Inject Dependencies to SignalR, should be always come before ASP.NET MVC configuration
var dependecyResolver = new SignalRSpringNetDependencyResolver(ContextRegistry.GetContext());
GlobalHost.DependencyResolver = dependecyResolver;
RouteTable.Routes.MapHubs();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
However, SignalR is always trying to resolve it's own dependencies using the Resolver i assigned and i get the following error:
'myhub' hub could not be resolved.
I only need the resolver to be aware of other dependencies(my Repository for example) and keep the default implementation of SignalR services.
I think it's hard to get Spring.Net working with SignalR
for the current version (Spring.Net 1.3.2) it's difficult to support asynchronous programming. Spring.Net session management doesn't play well with Task<T> types.
I ended up injecting my dependencies in 2 steps:
1- registering the required type on WebActivator PostStart:
GlobalHost.DependencyResolver.Register(
typeof(IUserService),
() => (UserService)ctx.GetObject("UserService"))
2- picking them up in my Hub constructor:
public MyHub()
{
_userService =
DependencyResolver.Current.GetService<IUserService>();
}
I’m using S#harp Architecture, has anyone found a way to access SQL Azure Federations with it?
I am aware that the following command must be executed outside of the transaction since SQL Azure does not allow “use Federation” statements within a transaction.
use Federation CustomerFederation (CustomerID=2) with reset, filtering=on
GO
<some sql statement...>
GO
There is another post on here that shows an example with creating a custom NHibernate Session class, but how can this be accomplished/extended using S#arp Architecture?
I'm also aware that there are other sharding options to SQL Azure Federation such as NHibernate.Shards or a multi-tenant S#arp Architecture extension but, please, keep to answering the question as opposed to providing other options.
I know I’m not the only person using S#arp Architecture and SQL Azure Federations and Google hasn't provided much so if anyone else out their has found a solution then, please, share.
Since no one has yet to respond to my post I am responding to it after several days of research. I was able to integrated with S#harp with 1 interface and 3 classes (I was hoping their would be an out of the box solution?).
The code provided below can be copied and pasted to any application and it should just work. The only exception is the FederationSessionHelper class. This is specific to each application as to were you are getting the info may change. I have an app setting section within my web.config that has the Federation name etc. Also, when the user authenticates, I parse the root url they are comming from then query the Federation Root to find out what tenant they are (I have a custom Tenant table I created). I then place the tenant ID in session under key "FederationKeyValue_Key" which will then be used in the FederationSession class to build the Use Federation statement.
/// <summary>
/// Interface used to retrieve app specific info about your federation.
/// </summary>
public interface IFederationSessionHelper
{
string ConnectionString { get; }
string FederationName { get; }
string DistributionName { get; }
string FederationKeyValue { get; }
}
/// <summary>
/// This is were you would get things specific for your application. I have 3 items in the web.config file and 1 stored in session. You could easily change this to get them all from the repository or wherever meets the needs of your application.
/// </summary>
public class FederationSessionHelper : IFederationSessionHelper
{
private const string ConnectionStringKey = "ConnectionString_Key";
private const string FederationNameKey = "FederationName_Key";
private const string DistributionNameKey = "DistributionName_Key";
private const string FederationKeyValueKey = "FederationKeyValue_Key";
public string ConnectionString { get { return ConfigurationManager.ConnectionStrings[ConnectionStringKey].ConnectionString; } }
public string FederationName { get { return ConfigurationManager.AppSettings[FederationNameKey]; } }
public string DistributionName { get { return ConfigurationManager.AppSettings[DistributionNameKey]; } }
//When user authenitcates, retrieve key value and store in session. This will allow to retrieve here.
public string FederationKeyValue { get { return Session[FederationKeyValueKey]; } }
}
/// <summary>
/// This is were the magic begins and where the integration with S#arp occurs. It manually creates a Sql Connections and adds it the S#arps storage. It then runs the Use Federation command and leaves the connection open. So now when you use an NhibernateSession.Current it will work with Sql Azure Federation.
/// </summary>
public class FederationSession : IDisposable
{
private SqlConnection _sqlConnection;
public void Init(string factoryKey,
string federationName,
string distributionName,
string federationKeyValue,
bool doesFilter,
string connectionString)
{
var sql = string.Format("USE FEDERATION {0}({1} = '{2}') WITH RESET, FILTERING = {3};", federationName, distributionName, federationKeyValue, (doesFilter) ? "ON" : "OFF");
_sqlConnection = new SqlConnection(connectionString);
_sqlConnection.Open();
var session = NHibernateSession.GetSessionFactoryFor(factoryKey).OpenSession(_sqlConnection);
NHibernateSession.Storage.SetSessionForKey(factoryKey, session);
var query = NHibernateSession.Current.CreateSQLQuery(sql);
query.UniqueResult();
}
public void Dispose()
{
if (_sqlConnection != null && _sqlConnection.State != ConnectionState.Closed)
_sqlConnection.Close();
}
}
/// <summary>
/// This was just icing on the cake. It inherits from S#arps TransactionAttribute and calls the FederationSession helper to open a connection. That way all you need to do in decorate your controller with the newly created [FederationTransaction] attribute and thats it.
/// </summary>
public class FederationTransactionAttribute : TransactionAttribute
{
private readonly string _factoryKey = string.Empty;
private bool _doesFilter = true;
/// <summary>
/// When used, assumes the <see cref = "factoryKey" /> to be NHibernateSession.DefaultFactoryKey
/// </summary>
public FederationTransactionAttribute()
{ }
/// <summary>
/// Overrides the default <see cref = "factoryKey" /> with a specific factory key
/// </summary>
public FederationTransactionAttribute(string factoryKey = "", bool doesFilter = true)
: base(factoryKey)
{
_factoryKey = factoryKey;
_doesFilter = doesFilter;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var federationSessionHelper = ServiceLocator.Current.GetInstance<IFederationSessionHelper>();
var factoryKey = GetEffectiveFactoryKey();
new FederationSession().Init(factoryKey,
federationSessionHelper.FederationName,
federationSessionHelper.DistributionName,
federationSessionHelper.FederationKeyValue,
_doesFilter,
federationSessionHelper.ConnectionString);
NHibernateSession.CurrentFor(factoryKey).BeginTransaction();
}
private string GetEffectiveFactoryKey()
{
return String.IsNullOrEmpty(_factoryKey) ? SessionFactoryKeyHelper.GetKey() : _factoryKey;
}
}
Now I am able to replace S#arp's [Transaction] attribute with the newly created [FederationTransaction] as follows:
[HttpGet]
[FederationTransaction]
public ActionResult Index()
{
var viewModel = NHibernateSession.Current.QueryOver<SomeDemoModel>().List()
return View(viewModel);
}
None of the code within the Controller needs to know that its using Sql Azure Federation. It should all just work.
Any thoughts? Anyone found a better solution? Please, share.
I have created a service data access layer where there are multiple databases where data needs to come from.
I was doing fine with one database where I defined the memberRepository that contained member details. However, now I have to get session-related details that are stored in another database.
OprationContracts:
IMemberServices contains GetLoggedInBuddies(int profileID);
ISessionServices contains GetProfileIDFromSessionID(string sessionID);
My service class:
public class MemberService : IMemberService, ISessionServices
{
#region Strategy pattern configuration
//
// Member repo
//
private MemberRepository memberRepository;
public MemberService()
: this(new MemberRepository())
{ }
public MemberService(MemberRepository memberRepository)
{
this.memberRepository = memberRepository;
}
//
// Session repo
//
private SessionRepository sessionRepository;
public MemberService() : this(new SessionRepository()){}
public MemberService(SessionRepository sessionRepository)
{
this.sessionRepository = sessionRepository;
}
#endregion
/// <summary>
/// Session-related details are maintained in the Secondary database
/// </summary>
/// <param name="sessionID"></param>
/// <returns></returns>
public int GetProfileIDFromSessionID(string sessionID)
{
int sessionProfileID = sessionRepository.GetProfileDetailsFromSessionID(sessionRepository);
return sessionProfileID;
}
/// <summary>
/// Try profileID = 1150526
/// </summary>
/// <param name="profileID"></param>
public void GetLoggedInBuddies(int profileID)
{
memberRepository.GetLoggedInBuddies(profileID);
//return memberRepository.GetLoggedInBuddies(profileID);
}
The issue is that in the // Session Repo section, as I already have a constructor defined. I get that.
So basically in each method I want to do something like
MemberService useSessionRepo = new MemberService(SessionRepository);
useSessionRepo.GetProfileDetailsFromSessionID(...);
MemberService useMemberRepo = new MemberService(MemberRepository);
useMemberRepo.GetLoggedInBuddies(...);
Just need a hand putting this together.
Thanks.
I'm not sure about your issue, but you can use a ctor without param, and with param for each repo.
public MemberService()
{
this.memberRepository = new MemberRepository();
this.sessionRepository = new SessionRepository();
}
I created a central repository that accepts the name of the connection string of the database I want to connect to.
public abstract class DatabaseRepository : BaseRepository
{
static IDbConnection connection;
/// <summary>
/// Handles db connectivity as Dapper assumes an existing connection for all functions
/// Since this app uses three databases, pass in the connection string for the required db.
/// </summary>
/// <returns></returns>
protected static IDbConnection OpenConnection(string connectionStringName)
{
try
{
connection = new SqlConnection(WebConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString);
//connection = SqlMapperUtil.GetOpenConnection(connectionStringName); // if we want to use the Dapper utility methods
connection.Open();
return connection;
}
catch (Exception ex)
{
ErrorLogging.Instance.Fatal(ex); // uses singleton for logging
return null;
}
}
.
.
.
Then in my service library, I make the connection to the appropriate db and perform whatever queries I need:
using (IDbConnection connection = OpenConnection("FirstDBConnectionString")) { ...
Imagine I have the following classes and interfaces:
public interface IService<T> { }
public class DefaultService<T> : IService<T> { }
public class FooService : IService<Foo> { }
public class BarService : IService<Bar> { }
I would then like to be able to get instances from the Kernel like this:
Kernel.Get<IService<Foo>>(); // Should return FooService
Kernel.Get<IService<Bar>>(); // Should return BarService
Kernel.Get<IService<Dog>>(); // Should return DefaultService
Kernel.Get<IService<Cat>>(); // Should return DefaultService
Kernel.Get<IService<Giraffe>>(); // Should return DefaultService
Is it possible to setup bindings using NInject (possibly using the Conventions extension), so that I don't have to manually bind every single possible implementation of IService?
I've been working on something similar recently and came up with somewhat simpler solution of your problem (although a bit weaker).
What should suffice is to bind a generic implementation (DefaultService) to the generic interface, and concrete implementations (FooService, BarService) to the concrete interfaces. When you ask for a concrete instance of the interface, Ninject resolves whether you defined the concrete binding. If you did, it gives you the appropriate instance, otherwise it falls through to the generic binding. The following code should do the trick.
var kernel = new StandardKernel();
kernel.Bind(typeof(IService<>)).To(typeof(DefaultService<>));
kernel.Bind<IService<Foo>>().To<FooService>();
kernel.Bind<IService<Bar>>().To<BarService>();
EDIT:
The concept works throughout the whole Ninject, so you can use it along with Extensions.Conventions as well.
e.g. define the following:
public class Foo{}
public class Bar{}
public class Dog{}
public interface IService<T>{}
public class DefaultService<T> : IService<T>{}
public class FooService : IService<Foo>{}
public class BarService : IService<Bar>{}
use conventions to bind the services:
kernel.Bind(x => x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(IService<>))
.BindSingleInterface());
and create and check the appropriate services:
Assert.IsInstanceOf<BarService>(kernel.Get<IService<Bar>>());
Assert.IsInstanceOf<FooService>(kernel.Get<IService<Foo>>());
Assert.IsInstanceOf<DefaultService<Dog>>(kernel.Get<IService<Dog>>());
I took the liberty of refactoring the answer from #cbp, so that it works for the new IBindingGenerator signature in Ninject v3 conventions. It's pretty much replacing the Process() method signature with the CreateBindings() method signature, but I didn't test this, so there's a chance you'll have to tweak it a bit if you use it.
/// <summary>
/// Creates bindings on open generic types.
/// This is similar to the out-of-the-box
/// <see cref="GenericBindingGenerator" />,
/// but allows a default class to be
/// specified if no other bindings can be found.
/// See the test case for usages.
/// </summary>
public class GenericBindingGeneratorWithDefault : IBindingGenerator
{
private static readonly Type TypeOfObject = typeof(object);
private readonly Type _contractType;
private readonly Dictionary<Type, Type> _cachedBindings;
private readonly Type _defaultType;
public GenericBindingGeneratorWithDefault(Type contractType, Type defaultType)
{
if (!(contractType.IsGenericType || contractType.ContainsGenericParameters))
throw new ArgumentException("The contract must be an open generic type.",
"contractType");
_cachedBindings = new Dictionary<Type, Type>();
_contractType = contractType;
_defaultType = defaultType;
}
/// <summary>
/// Creates the bindings for a type.
/// </summary>
/// <param name="type">The type for which the bindings are created.</param>
/// <param name="bindingRoot">The binding root that is used to create the bindings.</param>
/// <returns>
/// The syntaxes for the created bindings to configure more options.
/// </returns>
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
if (type == null) throw new ArgumentNullException("type");
if (bindingRoot == null) throw new ArgumentNullException("bindingRoot");
if (type.IsInterface || type.IsAbstract) yield break;
if (type == _defaultType)
{
yield return bindingRoot.Bind(_contractType).ToMethod(
ctx =>
{
Type requestedType = ctx.Request.Service;
Type resolution = _cachedBindings.ContainsKey(requestedType)
? _cachedBindings[requestedType]
: _defaultType.MakeGenericType(ctx.GenericArguments);
return ctx.Kernel.Get(resolution);
});
}
else
{
Type interfaceType = ResolveClosingInterface(type);
if (interfaceType != null)
{
yield return bindingRoot.Bind(type).To(_cachedBindings[interfaceType]);
}
}
}
/// <summary>
/// Resolves the closing interface.
/// </summary>
/// <param name="targetType">Type of the target.</param>
/// <returns></returns>
private Type ResolveClosingInterface(Type targetType)
{
if (targetType.IsInterface || targetType.IsAbstract) return null;
do
{
Type[] interfaces = targetType.GetInterfaces();
foreach (Type #interface in interfaces)
{
if (!#interface.IsGenericType) continue;
if (#interface.GetGenericTypeDefinition() == _contractType)
{
return #interface;
}
}
targetType = targetType.BaseType;
} while (targetType != TypeOfObject);
return null;
}
}
I figured out how to do this after a couple of hours messing around with NInject Convention's GenericBindingGenerator.
If anyone is interested I can post it.
Update:
/// <summary>
/// Creates bindings on open generic types.
/// This is similar to the out-of-the-box <see cref="GenericBindingGenerator" />, but allows a default class to be
/// specified if no other bindings can be found. See the test case for usages.
/// </summary>
public class GenericBindingGeneratorWithDefault : IBindingGenerator
{
private static readonly Type TYPE_OF_OBJECT = typeof (object);
private readonly Type _contractType;
private Dictionary<Type, Type> _cachedBindings = new Dictionary<Type, Type>();
private readonly Type _defaultType;
public GenericBindingGeneratorWithDefault(Type contractType, Type defaultType)
{
if ( !( contractType.IsGenericType || contractType.ContainsGenericParameters ) )
{
throw new ArgumentException( "The contract must be an open generic type.", "contractType" );
}
_contractType = contractType;
_defaultType = defaultType;
}
/// <summary>
/// Processes the specified type creating kernel bindings.
/// </summary>
/// <param name="type">The type to process.</param>
/// <param name="scopeCallback">the scope callback.</param>
/// <param name="kernel">The kernel to configure.</param>
public void Process( Type type, Func<IContext, object> scopeCallback, IKernel kernel )
{
if (type == _defaultType)
{
kernel.Bind(_contractType).ToMethod(
ctx =>
{
var requestedType = ctx.Request.Service;
var resolution = _cachedBindings.ContainsKey(requestedType)
? _cachedBindings[requestedType]
: _defaultType.MakeGenericType(ctx.GenericArguments);
return ctx.Kernel.Get(resolution);
});
}
else
{
Type interfaceType = ResolveClosingInterface(type);
if (interfaceType != null)
{
_cachedBindings[interfaceType] = type;
}
}
}
/// <summary>
/// Resolves the closing interface.
/// </summary>
/// <param name="targetType">Type of the target.</param>
/// <returns></returns>
public Type ResolveClosingInterface( Type targetType )
{
if ( targetType.IsInterface || targetType.IsAbstract )
{
return null;
}
do
{
Type[] interfaces = targetType.GetInterfaces();
foreach ( Type #interface in interfaces )
{
if ( !#interface.IsGenericType )
{
continue;
}
if ( #interface.GetGenericTypeDefinition() == _contractType )
{
return #interface;
}
}
targetType = targetType.BaseType;
} while ( targetType != TYPE_OF_OBJECT );
return null;
}
}