Why can't I get signalr to work with autofac dependency injection? - autofac

I'm new to AutoFac, but I thought this would be pretty straight forward. I've got a simple Hub:
public class Chat : Hub
{
private readonly IHomeTasks _homeTasks;
public Chat(IHomeTasks homeTasks)
{
_homeTasks = homeTasks;
}
public void Send(string text)
{
_homeTasks.DoNothing();
Clients.addMessage(text);
var user = new UserDocument { Username = text };
}
}
In my Global.ascx.cs I have:
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces();
builder.RegisterType<Helpers.AutofacDependencyResolver>().As<SignalR.IDependencyResolver>(); // Not sure if I need this or...
var container = builder.Build();
RouteTable.Routes.MapHubs(new Helpers.AutofacDependencyResolver(container));
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
and my AutofacDependencyResolver I just copied from here:
public class AutofacDependencyResolver : DefaultDependencyResolver, IRegistrationSource
{
private readonly ILifetimeScope _lifetimeScope;
public AutofacDependencyResolver(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
_lifetimeScope.ComponentRegistry.AddRegistrationSource(this);
}
public override object GetService(Type serviceType)
{
object result;
if (_lifetimeScope.TryResolve(serviceType, out result))
{
return result;
}
return null;
}
public override IEnumerable<object> GetServices(Type serviceType)
{
object result;
if (_lifetimeScope.TryResolve(typeof(IEnumerable<>).MakeGenericType(serviceType), out result))
{
return (IEnumerable<object>)result;
}
return Enumerable.Empty<object>();
}
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var typedService = service as TypedService;
if (typedService != null)
{
var instance = base.GetServices(typedService.ServiceType);
if (instance != null)
{
return instance.Select(i => RegistrationBuilder.ForDelegate(i.GetType(), (c, p) => i).As(typedService.ServiceType)
.InstancePerMatchingLifetimeScope(_lifetimeScope.Tag)
.CreateRegistration());
}
}
return Enumerable.Empty<IComponentRegistration>();
}
bool IRegistrationSource.IsAdapterForIndividualComponents
{
get { return false; }
}
}
My HomeTasks looks like this:
public class HomeTasks : Sandbox.Tasks.IHomeTasks
{
public void DoNothing()
{
}
}
Doesn't look like anything is happening as I'm getting a error like this inside my SignalR.Hosting.AspNet.HttpTaskAsyncHandler:
Could not load type 'SignalR.Hosting.IRequest' from assembly 'SignalR,
Version=0.5.1.10625, Culture=neutral, PublicKeyToken=null'.
Edit:
I removed all SignalR dll's and then re-added due to dfowler's answer and everything comes up great but now when I actually invoke the Send(text) on my Chat Hub I get this:
[MissingMethodException: No parameterless constructor defined for this object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241
System.Activator.CreateInstance(Type type, Boolean nonPublic) +69
System.Activator.CreateInstance(Type type) +6
SignalR.Hubs.DefaultHubActivator.Create(HubDescriptor descriptor) +141
SignalR.Hubs.DefaultHubManager.ResolveHub(String hubName) +71
SignalR.Hubs.HubDispatcher.CreateHub(IRequest request, HubDescriptor descriptor, String connectionId, TrackingDictionary state, Boolean throwIfFailedToCreate) +679
SignalR.Hubs.HubDispatcher.OnReceivedAsync(IRequest request, String connectionId, String data) +870
SignalR.<>c__DisplayClass6.<ProcessRequestAsync>b__4(String data) +73
SignalR.Transports.ForeverTransport.ProcessSendRequest() +141
SignalR.Transports.ForeverTransport.ProcessRequestCore(ITransportConnection connection) +128
SignalR.Transports.ForeverTransport.ProcessRequest(ITransportConnection connection) +37
SignalR.PersistentConnection.ProcessRequestAsync(HostContext context) +1018
SignalR.Hubs.HubDispatcher.ProcessRequestAsync(HostContext context) +216
SignalR.Hosting.AspNet.AspNetHandler.ProcessRequestAsync(HttpContextBase context) +676
SignalR.Hosting.AspNet.HttpTaskAsyncHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +125
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8968180
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
I think I'm just missing one piece here I just can't figure out what the heck it is.
What leads me to thinking that the wiring for SignalR has problems is because I also have a simple controller that works fine.
public class HomeController : Controller
{
private IHomeTasks _homeTasks;
public HomeController(IHomeTasks homeTasks)
{
_homeTasks = homeTasks;
}
public ActionResult Index()
{
_homeTasks.DoNothing(); // No problems resolving HomeTasks!
}
Update with answer
protected void Application_Start()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()).AsImplementedInterfaces();
builder.RegisterType<Chat>().InstancePerLifetimeScope();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
RouteTable.Routes.MapHubs(new AutofacSignalrDependencyResolver(container));
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
Got it to work with the above AppStart method. The key line being the builder.RegisterType().InstancePerLifetimeScope();. I honestly don't know if this is the best way as this was sort of a learning experience for me as I figured this out using what I knew better [Windsor] but figured I had spent enough time that I wanted to at least see something from my labors. Hope this helps someone :D

It Looks like a version mismatch, that's probably why it can't load the type. Make sure you are using binary compatible versions of your dependencies.

Related

.Net Core API cant return result including System.Net.IPaddress

My Database is Postgressql which has INET type in .net i should use IPadress for mapping,but when i use it i get Page cant be reached error on client side,when i use String i get an error from database which says cant be cased to string from Inet
var rslt = _context.tenmins.Where(s => s.m_turbine_id == IPAddress.Parse("192.168.39.82" )&& s.m_time_stamp >= DateTime.Now.AddDays(-1)).Take(2).ToList();
return rslt ;
how to change to string after i get result,here is the screen shot of my result which could not be returned on browser!
For this issue, it is caused by that IPAddress is not friendly to serialize. You could try to implement your own JsonConverter.
IPAddressConverter
public class IPAddressConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(IPAddress));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return IPAddress.Parse((string)reader.Value);
}
}
Register Converter
services.AddMvc()
.AddJsonOptions(opt => {
opt.SerializerSettings.Converters.Add(new IPAddressConverter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
Controller Action
public List<Address> PostSql()
{
var rslt = _context.Addresses.Where(s => s.IP == IPAddress.Parse("192.168.39.82")).Take(2).ToList();
return rslt;
}

Why am I getting error: "Cannot access disposed object" in .net core 2 with EF and AutoFac?

First the error:
Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and
then later trying to use the same context instance elsewhere in your
application. This may occur if you are calling Dispose() on the
context, or wrapping the context in a using statement. If you are
using dependency injection, you should let the dependency injection
container take care of disposing context instances.
Object name: 'MemberContext'.
I have 3 projects, Domain, API and WebSPA app.
Domain has 2 modules, DomainModule and MediatorModule
public class DomainModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(MemberContext).Assembly)
.AsImplementedInterfaces()
.InstancePerLifetimeScope(); // via assembly scan
builder.RegisterType<MemberContext>().AsSelf()
.InstancePerLifetimeScope(); // or individually
}
}
public class MediatorModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
// enables contravariant Resolve() for interfaces with single contravariant ("in") arg
builder
.RegisterSource(new ContravariantRegistrationSource());
// mediator itself
builder
.RegisterType<Mediator>()
.As<IMediator>()
.InstancePerLifetimeScope();
// request handlers
builder
.Register<SingleInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t =>
{
object o;
return c.TryResolve(t, out o) ? o : null;
};
})
.InstancePerLifetimeScope();
// notification handlers
builder
.Register<MultiInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => (IEnumerable<object>) c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
})
.InstancePerLifetimeScope();
}
}
In API project I have also 2 modules, ApplicationModule and again MediatorModule same as the one above.
public class ApplicationModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(Startup).Assembly)
.AsImplementedInterfaces()
.InstancePerLifetimeScope(); // via assembly scan
builder.RegisterType<MemberContext>().AsSelf().InstancePerLifetimeScope(); // or individually
}
}
No, when I debug I can see that member context gets newed up on each request, yet on second request, it throws above error. To make sure I am not going crazy, I modified constructor of dbcontext to create an id for context so i can verify they are different. What am I doing wrong?
public MemberContext(DbContextOptions<MemberContext> options) : base(options)
{
MemberContextId = Guid.NewGuid();
Console.WriteLine("member context created: " + MemberContextId);
}
Here is the startup in API
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
// .AllowCredentials()
);
});
services.AddMvc()
.AddControllersAsServices();//Injecting Controllers themselves thru DI
//For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
AddSwaggerGen(services);
//var connection = Configuration["ConnectionString"];
//services.AddDbContext<MemberContext>(options => options.UseSqlServer(connection),ServiceLifetime.Scoped);
services.AddEntityFrameworkSqlServer()
.AddDbContext<MemberContext>(options =>
{
options.UseSqlServer(Configuration["ConnectionString"]
//,sqlServerOptionsAction: sqlOptions =>
//{
// sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
// sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
//}
);
},
ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
);
var container = new ContainerBuilder();
container.Populate(services);
container.RegisterAssemblyModules(typeof(VIN.Members.Domain.Entities.Member).Assembly,
typeof(Startup).Assembly);
return new AutofacServiceProvider(container.Build());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//NOTE: must be before UseMVC !!!
app.UseCors("CorsPolicy");
app.UseMvc();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
});
}
private void AddSwaggerGen(IServiceCollection services)
{
services.AddSwaggerGen(options =>
{
options.DescribeAllEnumsAsStrings();
options.SwaggerDoc("v1", new Swashbuckle.AspNetCore.Swagger.Info
{
Title = "VIN Members HTTP API",
Version = "v1",
Description = "Members Service HTTP API",
TermsOfService = "Terms Of Service"
});
});
}
}
UPDATE:
What I am trying to do is delete a record. On client side code looks like this
onDelete(item: IMember) {
//TODO: replace this with dialog service component
if (window.confirm('Are sure you want to delete this member?')) {
//put your delete method logic here
this.service.deleteMember(item).subscribe(x => {
this.getMembers();
});
}
}
this delete request gets mapped to a controller that passes it to mediator
Controller
// DELETE api/members/5
[HttpDelete("{id}")]
public void Delete(Guid id)
{
var command = new DeleteMember.Command(id);
_mediator.Send(command).ConfigureAwait(false);
}
and finally handler
public class DeleteMember
{
public class Command : IRequest
{
public Command(Guid memberId)
{
Guard.NotNull(memberId, nameof(memberId));
MemberId = memberId;
}
public Guid MemberId { get; }
}
public class Handler : AsyncRequestHandler<Command>
{
private MemberContext _context;
public Handler(MemberContext context)
{
_context = context;
Console.WriteLine("Delete member context: " + context.MemberContextId);
}
protected override async Task HandleCore(Command cmd)
{
try
{
var member = await _context.FindAsync<Member>(cmd.MemberId);//.ConfigureAwait(false);
// if (member != null)
//// {
_context.Remove(member);
await _context.SaveChangesAsync().ConfigureAwait(false);
// }
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
}
As you can see there is no code that disposes that context. Scratching my head.
See this commented out check for member if null. That was throwing error as well, I commented it out just to see what will happen, and now it throws as SaveChangesAsync.
As request completes, context gets disposed. Since command handler uses SaveChangesAsync(), context is disposed before save completes. Culprit is controller method :). It should be async as well.
[HttpDelete("{id}")]
public async Task Delete(Guid id)
{
var command = new DeleteMember.Command(id);
await _mediator.Send(command).ConfigureAwait(false);
}
Your DbContext is scoped, meaning that Dependency Injection will return the same DbContext object every time one is asked for within the same HTTP request (in the case of ASP.NET).
That means that you should not be calling Dispose on your DbContext (otherwise that same object can't be used a second time). That seems to be what is happening to you, intentionally or not.
That does mean you should not be using using with it. Are you using using anywhere in your code against your DbContext?
I don't think you showed the line where the Exception is being thrown.
Update:
Try overriding Dispose in your MemberContext class. Something like this:
public override void Dispose() {
base.Dispose();
}
But just set a breakpoint there. When it breaks (if it does) check the stack trace and see what called it.
This can also be caused by having async void instead of async Task within WebAPI in my experience.

How can I dynamically make entity properties read-only?

I'm working with EF 4.5 and DbContext. At business rules layer level, I should implement checks to avoid change entity value properties in some entity scenarios. Sample: StartProjecteDate should be readonly if ProjectIsStarted but not in other status.
I follow DRY principle, for this reason, I should be able to inspect readonly properties list from context and also from UI.
My question:
Is there a DataAnnotation validator that can dynamically set properties as readonly?
(and if not, is there a different / better solution to this problem?)
Notice than I'm working with Web Forms (and Telerik) architecture, a clean and elegant pattern will be welcome.
I'm trying to set and get at run time EditableAttribute as Jesse Webb explains, but I'm not able to get dataannotation attributes from property, my code:
<EditableAttribute(False)>
<MaxLength(400, ErrorMessage:="Màxim 400 caracters")>
Public Property NomInvertebrat As String
Edited Nov 8 2013 after digging docs, it seems that dataanottions if for class but for instance object itself. Perhaps an iReadonlyableProperties interface may be a way.
I have a class containing extension methods that lets me read data annotations like this:
int maxRefLen = ReflectionAPI.GetProperty<Organisation, String>(x => x.Name)
.GetAttribute<StringLengthAttribute>()
.GetValueOrDefault(x => x.MaximumLength, 256);
So if you use it you should be able to do get the value of the EditableAttribute like this:
bool isEditable = ReflectionAPI.GetProperty<Foo, String>(x => x.NomInvertebrat)
.GetAttribute<EditableAttribute>()
.GetValueOrDefault(x => x.AllowEdit, true);
As for setting the data annotations at run-time, I haven't done it myself but I have read that there is a solution here: Setting data-annotations at runtime
Getting a list of all data annotations of a particular type I think would entail reading the entity framework metadata. Again I haven't tried this.
If you add that together I personally think it feels clunky rather than elegant, but you have asked for a solution using DataAnnotations and something more elegant would probably mean getting into your architecture.
I would be inclined to do this:
public bool StartDateIsReadOnly
{
//use this property client-side to disable the input
get{ return Project.IsStarted;}
}
//Implement IValidatable object to do server side validation
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext
{
bool startdateIsChanged = // I'll leave you to work out this bit
var results = new List<ValidationResult>();
if(StartDateIsReadOnly && startdateIsChanged)
results.Add(new ValidationResult("Start Date cannot be changed after project is started");
}
Here is the ReflectionAPI class:
Please note that the class includes part of a hack that #JonSkeet posted and described as "evil". I personally think this bit ain't so bad, but you should read the following references:
Override a generic method for value types and reference types.
Evil code - overload resolution workaround
public static class ReflectionAPI
{
public static int GetValueOrDefault<TInput>(this TInput a, Func<TInput, int> func, int defaultValue)
where TInput : Attribute
//Have to restrict to struct or you get the error:
//The type 'R' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'
{
if (a == null)
return defaultValue;
return func(a);
}
public static Nullable<TResult> GetValueOrDefault<TInput, TResult>(this TInput a, Func<TInput, TResult> func, Nullable<TResult> defaultValue)
where TInput : Attribute
where TResult : struct
//Have to restrict to struct or you get the error:
//The type 'R' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'
{
if (a == null)
return defaultValue;
return func(a);
}
//In order to constrain to a class without interfering with the overload that has a generic struct constraint
//we need to add a parameter to the signature that is a reference type restricted to a class
public class ClassConstraintHack<T> where T : class { }
//The hack means we have an unused parameter in the signature
//http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx
public static TResult GetValueOrDefault<TInput, TResult>(this TInput a, Func<TInput, TResult> func, TResult defaultValue, ClassConstraintHack<TResult> ignored = default(ClassConstraintHack<TResult>))
where TInput : Attribute
where TResult : class
{
if (a == null)
return defaultValue;
return func(a);
}
//I don't go so far as to use the inheritance trick decribed in the evil code overload resolution blog,
//just create some overloads that take nullable types - and I will just keep adding overloads for other nullable type
public static bool? GetValueOrDefault<TInput>(this TInput a, Func<TInput, bool?> func, bool? defaultValue)
where TInput : Attribute
{
if (a == null)
return defaultValue;
return func(a);
}
public static int? GetValueOrDefault<TInput>(this TInput a, Func<TInput, int?> func, int? defaultValue)
where TInput : Attribute
{
if (a == null)
return defaultValue;
return func(a);
}
public static T GetAttribute<T>(this PropertyInfo p) where T : Attribute
{
if (p == null)
return null;
return p.GetCustomAttributes(false).OfType<T>().LastOrDefault();
}
public static PropertyInfo GetProperty<T, R>(Expression<Func<T, R>> expression)
{
if (expression == null)
return null;
MemberExpression memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
return null;
return memberExpression.Member as PropertyInfo;
}
}
.NET allows you to dynamically change structure of Class by implementing System.ComponentModel.ICustomTypeDescriptor. Most serializers support this interface.
// Sample Serialization
foreach(PropertyDescriptor p in TypeDescriptor.GetProperties(obj)){
string name = p.PropertyName;
object value = p.GetValue(obj);
}
Internally TypeDescriptor uses Reflection, but the implementation allows us to override reflection attributes easily.
Here are three steps of implementation,
// Implement System.ComponentModel.ICustomTypeDescriptor Interface on
// your Entity
public class MyEntity: System.ComponentModel.ICustomTypeDescriptor
{
....
// most methods needs only call to default implementation as shown below
System.ComponentModel.AttributeCollection
System.ComponentModel.ICustomTypeDescriptor.GetAttributes()
{
return TypeDescriptor.GetAttributes(this, true);
}
string System.ComponentModel.ICustomTypeDescriptor.GetClassName()
{
return TypeDescriptor.GetClassName(this, true);
}
string System.ComponentModel.ICustomTypeDescriptor.GetComponentName()
{
return TypeDescriptor.GetComponentName(this, true);
}
System.ComponentModel.TypeConverter System.ComponentModel.ICustomTypeDescriptor.GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
System.ComponentModel.EventDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}
System.ComponentModel.PropertyDescriptor System.ComponentModel.ICustomTypeDescriptor.GetDefaultProperty()
{
return TypeDescriptor.GetDefaultProperty(this, true);
}
object System.ComponentModel.ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(this, editorBaseType, true);
}
System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(this, attributes, true);
}
System.ComponentModel.EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents()
{
return TypeDescriptor.GetEvents(this, true);
}
System.ComponentModel.PropertyDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
{
return TypeDescriptor.GetProperties(this, attributes, true);
}
object System.ComponentModel.ICustomTypeDescriptor.GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd)
{
return this;
}
// The Only method that needs different implementation is below
System.ComponentModel.PropertyDescriptorCollection
System.ComponentModel.ICustomTypeDescriptor.GetProperties()
{
// ... you are supposed to create new instance of
// PropertyDescriptorCollection with PropertyDescriptor
PropertyDescriptorCollection pdc = new PropertyDescriptorCollection();
foreach(PropertyDescriptor p in TypeDescriptor.GetProperties(this,true)){
// if readonly..
AtomPropertyDescriptor ap = new AtomPropertyDescriptor(p, p.Name);
// or
AtomPropertyDescriptor ap = new AtomPropertyDescriptor(p, p.Name,
true,
new XmlIgnoreAttribute(),
new ScriptIgnoreAttribute(),
new ReadOnlyAttribute());
pdc.Add(ap);
}
return pdc;
}
}
// And here is the AtomPropertyDescriptorClass
public class AtomPropertyDescriptor : PropertyDescriptor
{
PropertyDescriptor desc;
bool? readOnly = null;
public AtomPropertyDescriptor(PropertyDescriptor pd, string name,
bool? readOnly, params Attribute[] attrs) :
base(name, attrs)
{
desc = pd;
this.readOnly = readOnly;
}
public override bool CanResetValue(object component)
{
return desc.CanResetValue(component);
}
public override Type ComponentType
{
get
{
return desc.ComponentType;
}
}
public override object GetValue(object component)
{
return desc.GetValue(component);
}
public override bool IsReadOnly
{
get
{
if (readOnly.HasValue)
return readOnly.Value;
return desc.IsReadOnly;
}
}
public override Type PropertyType
{
get { return desc.PropertyType; }
}
public override void ResetValue(object component)
{
desc.ResetValue(component);
}
public override void SetValue(object component, object value)
{
desc.SetValue(component, value);
}
public override bool ShouldSerializeValue(object component)
{
return desc.ShouldSerializeValue(component);
}
}
I think what you are looking for is a custom Annotation Attribute like this:
<DisableEditAttribute(this.IsProjectStarted)>
Public Property NomInvertebrat As String
public override bool IsValid(bool value)
{
bool result = true;
// Add validation logic here.
if(value)
{
//Compare Current Value Against DB Value.
}
return result;
}
See MSDN: http://msdn.microsoft.com/en-us/library/cc668224(v=vs.98).aspx

GWT JSNI BOOLEAN

Here's my code:
package com.eggproject_hu.WPECommerceAdminSales.client;
import java.lang.Boolean;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
public class AblakVillogo
{
public static Boolean focusedWindow = true;
private static Boolean init = false;
public static void setFocused(Boolean focus)
{
focusedWindow = focus;
}
public static Boolean getFocused()
{
return focusedWindow;
}
public static void focusVizsgalat()
{
if(focusedWindow == true)
{
GWT.log("igen");
}
else
{
GWT.log("nem");
}
}
public static void init()
{
if(init == false)
{
_init();
}
}
private native static void _init() /*-{
$wnd.jQuery(document).ready(function()
{
$wnd.jQuery($wnd).focus(function()
{
#com.eggproject_hu.WPECommerceAdminSales.client.AblakVillogo::focusVizsgalat()(); #com.eggproject_hu.WPECommerceAdminSales.client.AblakVillogo::setFocused(Ljava/lang/Boolean;)(true);
$wnd.console.log("focus");
}).blur(function()
{
var ret = false;
#com.eggproject_hu.WPECommerceAdminSales.client.AblakVillogo::focusVizsgalat()();
#com.eggproject_hu.WPECommerceAdminSales.client.AblakVillogo::setFocused(Ljava/lang/Boolean;)(false);
$wnd.console.log("blur");
});
});
}-*/;
}
I see this in the browser console:
uncaught exception: java.lang.IllegalArgumentException: invoke arguments: JS value of type boolean, expected java.lang.Boolean
I've tested in Chrome and Firefox.
What is the problem?
Thanks for the help!
You have to declare the Boolean as the primitive boolean to set the value from javascript
and you dont need to specifiy L/java/lang/Boolean in the call but Z instead
Either follow Daniel's advice, but then you have to change your method to take a boolean argument (i.e. use boolean all the way through), or you can explicitly cast/box your boolean in a java.lang.Boolean in your JSNI method:
#com.eggproject_hu.WPECommerceAdminSales.client.AblakVillogo::setFocused(Ljava/lang/Boolean;)(#java.lang.Boolean::valueOf(Z)(true));
…even though in your case, because the value is a constant, I'd rather directly use the Boolean constants TRUE and FALSE:
#com.eggproject_hu.WPECommerceAdminSales.client.AblakVillogo::setFocused(Ljava/lang/Boolean;)(#java.lang.Boolean::TRUE);
That being said, I do believe Daniel's advice is your best fit.

MVC source code singleton pattern

Why does .net MVC source code ControllerBuilder use a delegate to assign the controller factory?:
private Func<IControllerFactory> _factoryThunk;
public void SetControllerFactory(IControllerFactory controllerFactory) {
_factoryThunk = () => controllerFactory;
}
Why can't it just assign the ControllerFactory directly?, ie:
private IControllerFactory _factory;
public void SetControllerFactory(IControllerFactory controllerFactory) {
_factory = controllerFactory;
}
public void SetControllerFactory(Type controllerFactoryType) {
_factory = (IControllerFactory)Activator.CreateInstance(controllerFactoryType);
}
The reason that _factoryThunk is currently defined as a Func<IControllerFactory> is that it's a generic means to support both overloads:
void SetControllerFactory(Type);
void SetControllerFactory(IControllerFactory);
The implementation of the first one uses the fact that _factoryThunk is a Func by declaring that Func inline by using Activator to instantiate the Type lazily:
this._factoryThunk = delegate {
IControllerFactory factory;
try
{
factory = (IControllerFactory) Activator.CreateInstance(controllerFactoryType);
}
catch (Exception exception)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, MvcResources.ControllerBuilder_ErrorCreatingControllerFactory, new object[] { controllerFactoryType }), exception);
}
return factory;
};
Therefore, the reason the other overload looks like it has a spurious implementation is that since _factoryThunk is declared as a Func, the line you propose wouldn't have even compiled:
_factoryThunk = controllerFactory;
_factoryThunk is a Func<IControllerFactory> whereas controllerFactory is an IControllerFactory -- incompatible types.