problem navigating from app to baseview model with this base ctor - mvvmcross

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

Related

How does Asp.net Core renders a view

How does MVC 6 renders a view. What's the actual method in Razor ViewEngine that generates the html output? Also if possible please explain the process of rendering a view.
May be you could point me to a file on mvc source on github. thanks!
Here is a complete solution of what you are looking for. I used dependency injection to get the HtmlHelper in the controller. You can inject your own helper if you want too.
using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.Mvc.ViewFeatures.Internal;
using Microsoft.Extensions.WebEncoders;
using System.ComponentModel.DataAnnotations;
using System;
public class MyController : Controller
{
private readonly IHtmlGenerator htmlGenerator;
ICompositeViewEngine viewEngine;
IModelMetadataProvider metadataProvider;
private readonly IHtmlHelper helper;
IHtmlEncoder htmlEncoder;
IUrlEncoder urlEncoder;
IJavaScriptStringEncoder javaScriptStringEncoder;
public MyController(IHtmlHelper helper, IHtmlGenerator htmlGenerator, ICompositeViewEngine viewEngine, IModelMetadataProvider metadataProvider, IHtmlEncoder htmlEncoder, IUrlEncoder urlEncoder, IJavaScriptStringEncoder javaScriptStringEncoder)
{
this.htmlGenerator = htmlGenerator;
this.viewEngine = viewEngine;
this.metadataProvider = metadataProvider;
this.htmlEncoder = htmlEncoder;
this.urlEncoder = urlEncoder;
this.javaScriptStringEncoder = javaScriptStringEncoder;
this.helper = helper;
}
[HttpGet]
public IActionResult MyHtmlGenerator()
{
MyViewModel temp = new MyViewModel();
var options = new HtmlHelperOptions();
options.ClientValidationEnabled = true;
ViewDataDictionary<MyViewModel> dic = new ViewDataDictionary<MyViewModel>(this.metadataProvider, new ModelStateDictionary());
ViewContext cc = new ViewContext(ActionContext, new FakeView(), dic, TempData, TextWriter.Null, options);
var type = typeof(MyViewModel);
var metadata = this.metadataProvider.GetMetadataForType(type);
ModelExplorer modelEx = new ModelExplorer(this.metadataProvider, metadata, temp);
ViewData["Description"] = "test desc";
ViewData["Id"] = 1;
this.ViewData = new ViewDataDictionary(this.metadataProvider, new ModelStateDictionary());
IHtmlHelper<MyViewModel> dd = new HtmlHelper<MyViewModel>(this.htmlGenerator, this.viewEngine, this.metadataProvider, this.htmlEncoder, this.urlEncoder, this.javaScriptStringEncoder);
((ICanHasViewContext)dd).Contextualize(cc);
dd.ViewContext.ViewData = this.ViewData;
var desc = GetString(dd.TextBoxFor(m => m.ID));
var ID = GetString(dd.TextBoxFor(m => m.Description));
// Do whatever you want with the ID and desc
return new ContentResult() { Content = ID + desc };
}
public static string GetString(IHtmlContent content)
{
var writer = new System.IO.StringWriter();
content.WriteTo(writer, new HtmlEncoder());
return writer.ToString();
}
}
public class MyViewModel : BaseAssetViewModel
{
// [RegularExpression(#"^-?\d{1,13}(\.\d{0,5})?$|^-?\.\d{1,5}$")]
[Required]
public int ID { get; set; }
[MinLength(2)]
public string Description { get; set; }
// Property with no validation
public string Other { get; set; }
}
public class FakeView : IView
{
string IView.Path
{
get
{
throw new NotImplementedException();
}
}
public Task RenderAsync(ViewContext viewContext)
{
throw new InvalidOperationException();
}
Task IView.RenderAsync(ViewContext context)
{
throw new NotImplementedException();
}
}
I don't know if this may be of help, may be you have to start to look at tag helpers:
https://github.com/DamianEdwards/TagHelperStarterWeb
they're working to a different way to create helpers that integrate in the page in a more natural way.

gson flat json to nested objects needs serializer/deserializer?

I have some JSON coming in (I don't have any control or ability to change the structure and/or naming within the JSON...important to keep in mind in this question) that has a "flat" structure similar to this:
{
"name": "...",
"email": "...",
"box_background_color": "...",
"box_border_color": "...",
"box_text_color": "...",
...
}
Now, I can just create a simple object that keeps everything flat, like so:
public class Settings {
#SerializedName("name")
private String _name;
#SerializedName("email")
private String _emailAddress;
#SerializedName("box_background_color")
private String _boxBackgroundColor;
#SerializedName("box_border_color")
private String _boxBorderColor;
#SerializedName("box_text_color")
private String _boxTextColor;
...
}
However, I want everything associated with box settings to be in it's own class (BoxSettings). This is more like what I want:
public class Settings {
#SerializedName("name")
private String _name;
#SerializedName("email")
private String _emailAddress;
private BoxSettings _boxSettings
...
}
public class BoxSettings {
#SerializedName("box_background_color")
private String _boxBackgroundColor;
#SerializedName("box_border_color")
private String _boxBorderColor;
#SerializedName("box_text_color")
private String _boxTextColor;
...
}
I know that if the JSON was structured such that the box settings were nested then it would be easy to accomplish what I want, however, I don't have the ability to change the structure of the JSON, so please don't suggest that (I would do it if I could).
My question is this: Is creating an entire TypeAdapter the only way to accomplish what I want or can I still accomplish most of this with annotations? If it is not the only way, how else can I accomplish this without changing the JSON at all?
The following is an example of what I mean by "creating an entire TypeAdapter":
public class SettingsTypeAdapter implements JsonDeserializer<Settings>, JsonSerializer<Settings> {
#Override
public JsonElement serialize(Settings src, Type typeOfSrc, JsonSerializationContext context) {
// Add _name
// Add _emailAddress
// Add BoxSettings._boxBackgroundColor
// Add BoxSettings._boxBorderColor
// Add BoxSettings._boxTextColor
return jsonElement;
}
#Override
public Settings deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
// Read _name
// Read _emailAddress
// Read BoxSettings._boxBackgroundColor
// Read BoxSettings._boxBorderColor
// Read BoxSettings._boxTextColor
return settings;
}
}
The TypeAdapter is not the only way, but in this case would be the best way since you can associate the adapter with a Gson instance (or whatever library you are using) and have all your mapping code there.
Another way is to use JAVA reflection. I've used a version of the below code in my projects before but never with JSON and never with nested objects (mostly when there was no other choice or if i wanted to map a SQL result set to a Java object without calling resultSet.get... a lot of times).
This will work in this case.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.json.JSONObject;
public class Main {
public static void main(String[] args) {
try {
String json = "{\"name\": \"test name\", \"email\": \"email#email.com\", \"box_background_color\": \"red\", \"box_border_color\": \"orange\", \"box_text_color\": \"white\", \"test3_var2\":3}";
JSONObject jsonObject = new JSONObject(json);
System.out.println(jsonObject);
System.out.println();
/*
* need to parse JSON into a map of String, Object
*/
Map<String, Object> mapAll = new HashMap<String, Object>();
Iterator<String> iter = jsonObject.keys();
while (iter.hasNext()) {
String key = (String) iter.next();
Object value = jsonObject.get(key);
mapAll.put(key, value);
System.out.println(key + "::::" + value);
}
System.out.println();
/*
* use the mapper to generate the objects
*/
MyMapper<TestClass1> myMapper = new MyMapper<TestClass1>();
TestClass1 result = myMapper.mapToObject(mapAll, TestClass1.class);
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyMapper<T> {
#SuppressWarnings("unchecked")
public T mapToObject(Map<String, Object> flatStructure, Class<T> objectClass) {
T result = null;
Field[] fields = null;
try {
// new base object
result = objectClass.newInstance();
// get all of its fields
fields = objectClass.getDeclaredFields();
for (Field field : fields) {
// normal variable
if (field.isAnnotationPresent(MyColumn.class)) {
String variableKey = field.getAnnotation(MyColumn.class).variableKey();
setJavaFieldValue(result, field.getName(), flatStructure.get(variableKey));
}
// variable that is an object and itself has to be mapped
else if (field.isAnnotationPresent(MyInnerColumn.class)) {
String startsWith = field.getAnnotation(MyInnerColumn.class).startsWith();
// reduce the map to only have attributes that are related to this field
Map<String, Object> reducedMap = reduceMap(startsWith, flatStructure);
// make sure that there are attributes for the inner object
if (reducedMap != null) {
// map the inner object
MyMapper<T> myMapper = new MyMapper<T>();
T t2 = myMapper.mapToObject(reducedMap, (Class<T>) field.getType());
// set the mapped object to the base objecct
setJavaFieldValue(result, field.getName(), t2);
}
} else {
// no annotation on the field so ignored
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private Map<String, Object> reduceMap(String startsWith, Map<String, Object> mapToReduce) {
Map<String, Object> result = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : mapToReduce.entrySet()) {
if (entry.getKey().toLowerCase().startsWith(startsWith.toLowerCase())) {
result.put(entry.getKey(), entry.getValue());
}
}
return result.size() == 0 ? null : result;
}
private void setJavaFieldValue(Object object, String fieldName, Object fieldValue) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
boolean fieldAccess = field.isAccessible();
// make the field accessible
field.setAccessible(true);
field.set(object, fieldValue);
// put it back to the way it was
field.setAccessible(fieldAccess);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* Annotation for a regular variable / field
*/
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
#interface MyColumn {
// the variable's JSON key
String variableKey() default "";
}
/*
* Annotation for an inner / nested variable / field
*/
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
#interface MyInnerColumn {
/*
* JSON keys that start with this string will be
* associated with this nested field
*/
String startsWith() default "";
}
class TestClass1 {
#MyColumn(variableKey = "name")
private String _name;
#MyColumn(variableKey = "email")
private String _emailAddress;
#MyInnerColumn(startsWith = "box_")
private TestClass2 innerClass;
#MyInnerColumn(startsWith = "test3_")
private TestClass3 innerClass2;
#Override
public String toString() {
return "TestClass1 [_name=" + _name + ", _emailAddress=" + _emailAddress + ", innerClass=" + innerClass + ", innerClass2=" + innerClass2 + "]";
}
}
class TestClass2 {
#MyColumn(variableKey = "box_background_color")
private String _boxBackgroundColor;
#MyColumn(variableKey = "box_border_color")
private String _boxBorderColor;
#MyColumn(variableKey = "box_text_color")
private String _boxTextColor;
#Override
public String toString() {
return "TestClass2 [_boxBackgroundColor=" + _boxBackgroundColor + ", _boxBorderColor=" + _boxBorderColor
+ ", _boxTextColor=" + _boxTextColor + "]";
}
}
class TestClass3 {
#MyColumn(variableKey = "test3_var1")
private String _test3Var1;
#MyColumn(variableKey = "test3_var2")
private int _test3Var2;
#Override
public String toString() {
return "TestClass3 [_test3Var1=" + _test3Var1 + ", _test3Var2=" + _test3Var2 + "]";
}
}
Output
{"box_background_color":"red","box_text_color":"white","test3_var2":3,"name":"test name","email":"email#email.com","box_border_color":"orange"}
box_background_color::::red
box_text_color::::white
test3_var2::::3
name::::test name
email::::email#email.com
box_border_color::::orange
TestClass1 [_name=test name, _emailAddress=email#email.com, innerClass=TestClass2 [_boxBackgroundColor=red, _boxBorderColor=orange, _boxTextColor=white], innerClass2=TestClass3 [_test3Var1=null, _test3Var2=3]]

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

Ninject Load FromAssembliesInPath with a 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();
});
}
}