Ninject Load FromAssembliesInPath with a Constructor - constructor

if i say have code that works like this:
private static void LoadFromAssemblies(IKernel kernel)
{
string appPath = HttpContext.Current.Request.MapPath(HttpContext.Current.Request.ApplicationPath);
kernel.Scan(a =>
{
a.FromAssembliesInPath(string.Format(#"{0}\Extensions", appPath));
a.AutoLoadModules();
a.BindWithDefaultConventions();
a.InRequestScope();
});
}
and just assume that each class defined in the target assembly has a string argument in the constructor, how would i go about passing in the string argument from the code above?
Do i instead use an Interceptor?
Thanks in advance, John

In my project into some repositories I pass ISession (nHibernate) and to others connectionString for DataContext(Linq2SQL)
To pass the connection string I have created LinqConfiguration class
public class LinqConfiguration : ILinqConfiguration
{
private readonly string _connectionString;
public LinqConfiguration(string connectionString)
{
_connectionString = connectionString;
}
public string GetConnectionString()
{
return _connectionString;
}
}
My repository looks like this:
public class WebClientRepository : IWebClientRepository
{
private readonly WebClientDataClassesDataContext datacontext;
private ILinqConfiguration _linqconfig;
public WebClientRepository(ILinqConfiguration linqconfig)
{
_linqconfig = linqconfig;
datacontext = new WebClientDataClassesDataContext(_linqconfig.GetConnectionString());
}
//....
}
and binding using Conventions:
public class LinqRepositoryModule: NinjectModule
{
public override void Load()
{
Bind<ILinqConfiguration>()
.To<LinqConfiguration>()
.WithConstructorArgument("connectionString",
ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString
);
IKernel ninjectKernel = this.Kernel;
ninjectKernel.Scan(kernel =>
{
kernel.FromAssemblyContaining<IWebClientRepository>();
kernel.FromAssemblyContaining<WebClientRepository>();
kernel.Where(t => t != typeof(LinqConfiguration)); // interface is in the same assembly and it is already binded
kernel.BindWithDefaultConventions();
kernel.AutoLoadModules();
kernel.InRequestScope();
});
}
}

Related

No serializer found for class using Json

I have a basic SpringBoot 2.1.2.RELEASE app. Using Spring Initializer, JPA, embedded Tomcat, Thymeleaf template engine, and package as an executable JAR with a restful architecture
I have this object that I return in a RestMethod:
public class MenuAlarm {
/**
*
*/
public MenuAlarm() {
super();
}
/**
*
*/
public MenuAlarm(Menu menu) {
this.menuAlias = menu.getName();
this.menuId = menu.getId();
menu
.getAlerts()
.forEach(a -> alarms.add(new Alarm(a)));
}
class Alarm {
public Alarm(MenuAlert menuAlert) {
this.percentage = menuAlert.getPercentage();
if (menuAlert.getCriteria() > 1) {
this.increase = true;
} else {
this.increase = false;
}
this.enabled = menuAlert.isEnabled();
}
public Alarm() {
super();
}
Integer percentage;
boolean increase;
boolean enabled;
}
String menuAlias;
Long menuId;
List<Alarm> alarms = new ArrayList<Alarm>();
public String getMenuAlias() {
return menuAlias;
}
public void setMenuAlias(String menuAlias) {
this.menuAlias = menuAlias;
}
public Long getMenuId() {
return MenuId;
}
public void setMenuId(Long menuId) {
this.menuId = menuId;
}
public List<Alarm> getAlarms() {
return alarms;
}
public void setAlarms(List<Alarm> alarms) {
this.alarms = alarms;
}
}
but when I return the result I got this error:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.tdk.api.json.MenuAlarm$Alarm and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: com.tdk.api.json.UserAlerts[“menuAlarms"]->java.util.ArrayList[0]->com.tdk.api.json.MenuAlarm["alarms"]->java.util.ArrayList[0])`
You haven't told Jackson how to serialize the inner Alarm class.
Jackson will attempt to serialize it as a bean (thus the reference to BeanSerializer), but you haven't provided any JavaBeans-compatible getter methods on Alarm.
Your options are to either to write a custom serializer for Alarm, or add some public getter methods like getPercentage.
Use this annotation in the entity class. It soled that error.
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

problem navigating from app to baseview model with this base ctor

I have a base class on baseviewmodel.
I'm facing navigationservice implemented on 6.2 on debug shows problem navigating to another viewmodel.
debug shows userdialogs break.
Is there a problem using base class in this way with those parameters . anyone faced this kind of issue
public BaseViewModel(IMvxNavigationService navigationService,
ILoginService loginService,
UserDialogs userDialogs, IValidator validator) {
_navigationService = navigationService;
_loginService = loginService;
_userDialogs = userDialogs;
_validator = validator;
Title = TextSource.GetText(StringResourceKeys.Title);
IsBusyMessage = Resources.Strings.LoadingMesssage;
}
using gettext provider like this
public class ResourcexTextProvider : IMvxTextProvider
{
private readonly ResourceManager _resourceManager;
public ResourcexTextProvider(ResourceManager resourceManager)
{
_resourceManager = resourceManager;
CurrentLanguage = CultureInfo.CurrentUICulture;
}
public CultureInfo CurrentLanguage { get; set; }
public string GetText(string namespaceKey, string typeKey, string name)
{
string resolvedKey = name;
if (!string.IsNullOrEmpty(typeKey))
{
resolvedKey = $"{typeKey}.{resolvedKey}";
}
if (!string.IsNullOrEmpty(namespaceKey))
{
resolvedKey = $"{namespaceKey}.{resolvedKey}";
}
return _resourceManager.GetString(resolvedKey, CurrentLanguage);
}
public string GetText(string namespaceKey, string typeKey, string name, params object[] formatArgs)
{
string baseText = GetText(namespaceKey, typeKey, name);
if (string.IsNullOrEmpty(baseText))
{
return baseText;
}
return string.Format(baseText, formatArgs);
}
public bool TryGetText(out string textValue, string namespaceKey, string typeKey, string name)
{
throw new System.NotImplementedException();
}
public bool TryGetText(out string textValue, string namespaceKey, string typeKey, string name, params object[] formatArgs)
{
throw new System.NotImplementedException();
}
}
}
You're trying to inject UserDialogs userDialogs in the ctor of your BaseViewModel. My guess is that you missed registering the userDialogs.
First of all you should inject interfaces instead of implementations to improve maintainability:
Mvx.IocConstruct.RegisterType<IUserDialogs, UserDialogs>();
And if my guess is correct and you are using Acr.UserDialogs you should initialize it and register it as:
Mvx.IoCProvider.RegisterSingleton<IUserDialogs>(() => UserDialogs.Instance);
Then you can inject it in any ViewModel directly using the interface:
public BaseViewModel(IMvxNavigationService navigationService,
ILoginService loginService,
IUserDialogs userDialogs,
IValidator validator) {
_navigationService = navigationService;
_loginService = loginService;
_userDialogs = userDialogs;
_validator = validator;
Title = TextSource.GetText(StringResourceKeys.Title);
IsBusyMessage = Resources.Strings.LoadingMesssage;
}
HIH

WcfFacility and Sequence contains no elements error?

I have wcf library with service contracts and implementations.
[ServiceContract]
public interface IServiceProtoType
{
[OperationContract]
Response GetMessage(Request request);
[OperationContract]
String SayHello();
}
[DataContract]
public class Request
{
private string name;
[DataMember]
public string Name
{
get { return name; }
set { name = value; }
}
}
[DataContract]
public class Response
{
private string message;
[DataMember]
public string Message
{
get { return message; }
set { message = value; }
}
}
public class MyDemoService : IServiceProtoType
{
public Response GetMessage(Request request)
{
var response = new Response();
if (null == request)
{
response.Message = "Error!";
}
else
{
response.Message = "Hello, " + request.Name;
}
return response;
}
public string SayHello()
{
return "Hello, World!";
}
}
I have windows service project that references this library, where MyService is just an empty shell that inherits ServiceBase. This service is installed and running under local system.
static void Main()
{
ServiceBase.Run(CreateContainer().Resolve());
}
private static IWindsorContainer CreateContainer()
{
IWindsorContainer container = new WindsorContainer();
container.Install(FromAssembly.This());
return container;
}
public class ServiceInstaller : IWindsorInstaller
{
#region IWindsorInstaller Members
public void Install(IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
string myDir;
if (string.IsNullOrEmpty(AppDomain.CurrentDomain.RelativeSearchPath))
{
myDir = AppDomain.CurrentDomain.BaseDirectory;
}
else
{
myDir = AppDomain.CurrentDomain.RelativeSearchPath;
}
var wcfLibPath = Path.Combine(myDir , "WcfDemo.dll");
string baseUrl = "http://localhost:8731/DemoService/{0}";
AssemblyName myAssembly = AssemblyName.GetAssemblyName(wcfLibPath);
container
.Register(
AllTypes
.FromAssemblyNamed(myAssembly.Name)
.InSameNamespaceAs<WcfDemo.MyDemoService>()
.WithServiceDefaultInterfaces()
.Configure(c =>
c.Named(c.Implementation.Name)
.AsWcfService(
new DefaultServiceModel()
.AddEndpoints(WcfEndpoint
.BoundTo(new WSHttpBinding())
.At(string.Format(baseUrl,
c.Implementation.Name)
)))), Component.For<ServiceBase>().ImplementedBy<MyService>());
}
#endregion
}
In Client Console app I have the following code and I am getting the following error:
{"Sequence contains no elements"}
static void Main(string[] args)
{
IWindsorContainer container = new WindsorContainer();
string baseUrl = "http://localhost:8731/DemoService/{0}";
container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero);
container
.Register(
Types
.FromAssemblyContaining<IServiceProtoType>()
.InSameNamespaceAs<IServiceProtoType>()
.Configure(
c => c.Named(c.Implementation.Name)
.AsWcfClient(new DefaultClientModel
{
Endpoint = WcfEndpoint
.BoundTo(new WSHttpBinding())
.At(string.Format(baseUrl,
c.Name.Substring(1)))
})));
var service1 = container.Resolve<IServiceProtoType>();
Console.WriteLine(service1.SayHello());
Console.ReadLine();
}
I have an idea what this may be but you can stop reading this now (and I apologize for wasting your time in advance) if the answer to the following is no:
Is one (or more) of Request, Response, or MyDemoService in the same namespace as IServiceProtoType?
I suspect that Windsor is getting confused about those, since you are doing...
Types
.FromAssemblyContaining<IServiceProtoType>()
.InSameNamespaceAs<IServiceProtoType>()
... and then configuring everything which that returns as a WCF client proxy. This means that it will be trying to create proxies for things that should not be and hence a Sequence Contains no Elements exception (not the most useful message IMHO but crushing on).
The simple fix would be just to put your IServiceProtoType into its own namespace (I often have a namespace like XXXX.Services for my service contracts).
If that is not acceptable to you then you need to work out another way to identify just the service contracts - take a look at the If method for example or just a good ol' Component.For perhaps.

Force WCF Rest client to use Json deserializer regardless of content-type

How to force WCF Rest client to use Json deserializer regardless of content-type?
I am invoking a REST based web service through WCF.
The service returns JSON body, but has content-type "Application/xml". The WCF framework is now giving me the XmlException.
public class MessageFormatter : IClientMessageFormatter
{
private readonly IClientMessageFormatter _formatter;
public MessageFormatter(IClientMessageFormatter formatter)
{
_formatter = formatter;
}
public object DeserializeReply(System.ServiceModel.Channels.Message message, object[] parameters)
{
return _formatter.DeserializeReply(message, parameters);
}
}
that _formatter.DeserializeReply is throwing XmlException. I can't find any example anywhere to force json deserialization on reply.
Edit - The "message" object when moused over is throwing "{... Error reading body: System.Xml.XmlException: The data at the root level is invalid. Line 1, position 1. ...}"
That same object in another one of my project that communicate with a different REST service (Picasa web services) has a what seems like a xml serialised version of JSON object?? So the problem seems further up the stream. I need to find where this object is originating from. I'll go play around with MessageEncoder class.
Edit - (Adding more info)
public class MyBinding : WebHttpBinding
{
public MyBinding(WebHttpSecurityMode mode)
: base(mode)
{
}
public override BindingElementCollection CreateBindingElements()
{
var result = base.CreateBindingElements();
var replacements = result.OfType<MessageEncodingBindingElement>().ToList();
foreach (var messageEncodingBindingElement in replacements)
{
var index = result.IndexOf(messageEncodingBindingElement);
result.Remove(messageEncodingBindingElement);
result.Insert(index, new MyMessageEncodingBindingElement(messageEncodingBindingElement));
}
return result;
}
}
public class MyMessageEncodingBindingElement : MessageEncodingBindingElement
{
private readonly MessageEncodingBindingElement _element;
public MyMessageEncodingBindingElement(MessageEncodingBindingElement element)
{
_element = element;
}
public override BindingElement Clone()
{
var result = _element.Clone();
if (result is MessageEncodingBindingElement)
return new MyMessageEncodingBindingElement(result as MessageEncodingBindingElement);
return result;
}
public override MessageEncoderFactory CreateMessageEncoderFactory()
{
return new MyMessageEncoderFactory(_element.CreateMessageEncoderFactory());
}
}
The method CreateMessageEncoderFactory() is never called even when the constructor and Clone method are hit when breakpoints are set. Any help? I'm trying to set a custom MessageEncoder and MessageEncoderFactory class to modify the instantiation process of the Message object.
You can use a WebContentTypeMapper for that. That's a property of the WebHttpBinding, and you can customize how the deserialization will be done by the encoder from that binding, including forcing it to always use the JSON deserializer, regardless of the incoming message's Content-Type. The code below shows how this can be done.
public class StackOverflow_13225272
{
[DataContract]
public class Person
{
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
public override string ToString()
{
return string.Format("Person[Name={0},Age={1}]", Name, Age);
}
}
[ServiceContract]
public interface ITest
{
[WebGet(ResponseFormat = WebMessageFormat.Json)]
Person GetPerson(string responseContentType);
}
public class Service : ITest
{
public Person GetPerson(string responseContentType)
{
WebOperationContext.Current.OutgoingResponse.ContentType = responseContentType;
return new Person { Name = "John Doe", Age = 29 };
}
}
class AllJsonContentTypeMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Json;
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
host.Open();
Console.WriteLine("Host opened");
#if USE_NETFX4
// This works on .NET 4.0 and beyond
WebHttpBinding binding = new WebHttpBinding();
binding.ContentTypeMapper = new AllJsonContentTypeMapper();
#else
// This works on .NET 3.5
CustomBinding binding = new CustomBinding(new WebHttpBinding());
binding.Elements.Find<WebMessageEncodingBindingElement>().ContentTypeMapper = new AllJsonContentTypeMapper();
ChannelFactory<ITest> factory = new ChannelFactory<ITest>(binding, new EndpointAddress(baseAddress));
#endif
ChannelFactory<ITest> factory = new ChannelFactory<ITest>(binding, new EndpointAddress(baseAddress));
factory.Endpoint.Behaviors.Add(new WebHttpBehavior());
ITest proxy = factory.CreateChannel();
Console.WriteLine("With JSON: {0}", proxy.GetPerson("application/json"));
Console.WriteLine("With XML: {0}", proxy.GetPerson("application/xml"));
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
This might work.
public class ForceJsonClientMessageFormatter : IClientMessageFormatter
{
private readonly DataContractJsonSerializer _jsonSerializer;
public ForceJsonClientMessageFormatter(Type responseType)
{
_jsonSerializer = new DataContractJsonSerializer(responseType);
}
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
throw new NotImplementedException("This client message formatter is for replies only!");
}
public object DeserializeReply(Message message, object[] parameters)
{
string messageBody = message.GetBody<string>();
using (MemoryStream messageStream = new MemoryStream(Encoding.UTF8.GetBytes(messageBody)))
{
messageStream.Seek(0, SeekOrigin.Begin);
object deserializedObject = _jsonSerializer.ReadObject(messageStream);
return deserializedObject;
}
}
}
public class ForceJsonWebHttpBehavior : WebHttpBehavior
{
protected override IClientMessageFormatter GetReplyClientFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
{
return new ForceJsonClientMessageFormatter(operationDescription.Messages[1].Body.ReturnValue.Type);
}
}
I haven't tried it, but I think this will work. You can create a custom IClientMessageFormatter which overwrites the message format to Json, wrap that in a behavior, and then apply that behavior to your client endpoint configuration.
public class ForceJsonClientMessageFormatterDecorator : IClientMessageFormatter
{
private readonly IClientMessageFormatter _decoratedFormatter;
public ForceJsonClientMessageFormatterDecorator(IClientMessageFormatter decoratedFormatter)
{
_decoratedFormatter = decoratedFormatter;
}
public object DeserializeReply(Message message, object[] parameters)
{
message.Properties[WebBodyFormatMessageProperty.Name] = new WebBodyFormatMessageProperty(WebContentFormat.Json);
return _decoratedFormatter.DeserializeReply(message, parameters);
}
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
return _decoratedFormatter.SerializeRequest(messageVersion, parameters);
}
}
public class ForceJsonWebHttpBehavior : WebHttpBehavior
{
protected override IClientMessageFormatter GetReplyClientFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
{
IClientMessageFormatter decoratedFormatter = base.GetReplyClientFormatter(operationDescription, endpoint);
return new ForceJsonClientMessageFormatterDecorator(decoratedFormatter);
}
}

Trouble Passing Parameter to LinqToSql Stored Procedure

public IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters)
{
Type genericType = typeof(T);
string commandthing = genericType.Name.Replace("Result", "");
//_db is my Linq To Sql database
return _db.ExecuteQuery<T>(commandthing, parameters).AsEnumerable();
}
The stored procedure is named GetOrder and has a single int parameter of orderid. I'm calling the above like so:
SqlParameter parm1 = new SqlParameter("#orderid", SqlDbType.Int);
parm1.Value = 123;
var results =
_session.ExecuteStoredProcedure<GetOrderResult>(parm1).Single();
I'm receiving the following error: A query parameter cannot be of type 'System.Data.SqlClient.SqlParameter'
Thoughts? Or am I just missing something obvious?
Update: I'm trying to make this as generic as possible...my current thinking is that I'm going to have to do some string trickery to create the ExecuteQuery text and parameters.
Update: Posting below my Session Interface and my Linq to Sql Implementation of the interface...hopefully that will clarify what I'm attempting to do
public interface ISession : IDisposable
{
void CommitChanges();
void Delete<T>(Expression<Func<T, bool>> expression) where T : class;
void Delete<T>(T item) where T : class;
void DeleteAll<T>() where T : class;
T Single<T>(Expression<Func<T, bool>> expression) where T : class;
IQueryable<T> All<T>() where T : class;
void Add<T>(T item) where T : class;
void Add<T>(IEnumerable<T> items) where T : class;
void Update<T>(T item) where T : class;
IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters);
}
public class LinqToSqlSession : ISession
{
public readonly Db _db;
public LinqToSqlSession()
{
_db = new Db(ConfigurationManager.ConnectionStrings[Environment.MachineName].ConnectionString);
}
public void CommitChanges()
{
_db.SubmitChanges();
}
/// <summary>
/// Gets the table provided by the type T and returns for querying
/// </summary>
private Table<T> GetTable<T>() where T : class
{
return _db.GetTable<T>();
}
public void Delete<T>(Expression<Func<T, bool>> expression) where T : class
{
var query = All<T>().Where(expression);
GetTable<T>().DeleteAllOnSubmit(query);
}
public void Delete<T>(T item) where T : class
{
GetTable<T>().DeleteOnSubmit(item);
}
public void DeleteAll<T>() where T : class
{
var query = All<T>();
GetTable<T>().DeleteAllOnSubmit(query);
}
public void Dispose()
{
_db.Dispose();
}
public T Single<T>(Expression<Func<T, bool>> expression) where T : class
{
return GetTable<T>().SingleOrDefault(expression);
}
public IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters)
{
Type genericType = typeof(T);
string commandstring = genericType.Name.Replace("Result", "");
//_db is my Linq To Sql database
return _db.ExecuteQuery<T>(commandstring, parameters).AsEnumerable();
}
public IQueryable<T> All<T>() where T : class
{
return GetTable<T>().AsQueryable();
}
public void Add<T>(T item) where T : class
{
GetTable<T>().InsertOnSubmit(item);
}
public void Add<T>(IEnumerable<T> items) where T : class
{
GetTable<T>().InsertAllOnSubmit(items);
}
public void Update<T>(T item) where T : class
{
//nothing needed here
}
}
That isn't how you're supposed to wire up Stored Procedures with Linq-to-SQL. You should extend the DataContext and use ExecuteMethodCall instead:
Taken from MSDN:
public partial class MyDataContext
{
[Function()]
public IEnumerable<Customer> CustomerById(
[Parameter(Name = "CustomerID", DbType = "NChar(5)")]
string customerID)
{
IExecuteResult result = this.ExecuteMethodCall(this,
((MethodInfo)(MethodInfo.GetCurrentMethod())),
customerID);
return (IEnumerable<Customer>)(result.ReturnValue);
}
}
If you really must execute a sproc as a query (highly not recommended), then you have to preface the command with EXEC, and don't use SqlParameter either, the call would look like:
var results = context.ExecuteQuery<MyResult>("EXEC usp_MyProc {0}, {1}",
custID, custName);
(And I'll note, pre-emptively, that this is not a SQL injection vector because Linq to SQL turns the curly braces into a parameterized query.)
Read about how to call sprocs in linq to sql
http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx
Had the same Problem. The following approach worked 4 me.
public interface IBusinessEntityRepository
{
.......
object CallStoredProcedure(string storedProcedureName, object[] parameters);
}
implementation in my linqtosql GenericLinqRepository
public object CallStoredProcedure(string storedProcedureName, object[] parameters)
{
DataContext dataContext = GetCurrentDataContext();
MethodInfo method = dataContext.GetType().GetMethod(storedProcedureName);
return method.Invoke(dataContext, parameters);
}
I'm sure there is a better way to do this...but this is presently working:
public IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters)
{
Type genericType = typeof(T);
StringBuilder sb=new StringBuilder();
sb.Append("EXEC ");
sb.Append(genericType.Name.Replace("Result", " " ));
for (int i = 0; i < parameters.Count(); i++)
{
sb.Append("{" + i.ToString() + "} ");
}
string commandstring = sb.ToString();
return _db.ExecuteQuery<T>(commandstring, parameters);
}
It's a little bit brittle in that your parameters must be set up in the proper order, and it's probably offensive to some...but it does accomplish the goal.
You can use this instead:
new SqlParameter { ParameterName = "UserID", Value =txtuserid.Text }
This equivalent in System.Data.SqlClient to :
SqlParameter[] param=new SqlParameter[2];
param[0]=new SqlParameter("#UserID",txtuserid)