I was following this example
example code:
public class Global : HttpApplication
{
private Poster _posterDetails;
private Posting _postingDetails;
private Property _propertyDetails;
protected void Application_PostRequestHandlerExecute(object sender, EventArgs e)
{
if (HttpContext.Current.Session == null) return;
_posterDetails = HttpContext.Current.Session["Poster"] as Poster;
_postingDetails = HttpContext.Current.Session["Posting"] as Posting;
_propertyDetails = HttpContext.Current.Session["Property"] as Property;
}
}
these session variables are littered throughout the app and I need to abstract the retrieval of them. Say, later I get them from a db instead of the current session.
Session is baked into the Page or Context. How do I inject that dependency into the concrete implementation of a possible current property getter.
Create an abstraction around HttpContext:
public interface IHttpContextFactory
{
HttpContextBase Create();
}
public class HttpContextFactory
: IHttpContextFactory
{
public HttpContextBase Create()
{
return new HttpContextWrapper(HttpContext.Current);
}
}
Then inject it into a specialized service for these settings.
public interface ISettings
{
T GetValue<T>(string key);
void SetValue<T>(string key, T value);
}
public class ContextSettings
: ISettings
{
private readonly IHttpContextFactory httpContextFactory;
private HttpContextBase context;
public RequestCache(
IHttpContextFactory httpContextFactory
)
{
if (httpContextFactory == null)
throw new ArgumentNullException("httpContextFactory");
this.httpContextFactory = httpContextFactory;
}
protected HttpContextBase Context
{
get
{
if (this.context == null)
{
this.context = this.httpContextFactory.Create();
}
return context;
}
}
public virtual T GetValue<T>(string key)
{
if (this.Context.Session.Contains(key))
{
return (T)this.Context.Session[key];
}
return default(T);
}
public virtual void SetValue<T>(string key, T value)
{
this.Context.Session[key] = value;
}
}
It will later be possible to replace the service with another storage mechanism by implementing ISettings and providing different constructor dependencies. Note that changing the constructor signature does not require a different interface.
That said, you should provide another service (or perhaps more than one) that takes ISettings as a dependency so you can make explicit properties. You should aim to provide focused sets of related properties for specific purposes. Your application also shouldn't have to know the type of property in order to retrieve its value - it should just call a property that hides those details.
public class SomeSettingsService: ISomeSettingsService
{
private readonly ISettings settings;
public SomeSettingsService(ISettings settings)
{
if (settings == null)
throw new ArgumentNullException("settings");
this.settings = settings;
}
public Poster Poster
{
get { return this.settings.GetValue<Poster>("Poster"); }
set { this.settings.SetValue<Poster>("Poster", value); }
}
public Posting Posting
{
get { return this.settings.GetValue<Posting>("Posting"); }
set { this.settings.SetValue<Posting>("Posting", value); }
}
public Property Property
{
get { return this.settings.GetValue<Property>("Property"); }
set { this.settings.SetValue<Property>("Property", value); }
}
}
Not sure if this is what you are asking... What I often do is create a service:
public interface ISessionService
{
object Get(string key);
void Save(string key, object value);
}
And then I implement this, which calls HttpContext.Current.Session[key] and returns the value. It shouldn't be hard to create a Get<T>(string key) to return an object either. Break all of your dependencies to use this (which is the hard part).
There is no seamless way to break the dependency... it has to be through a manual change.
Related
Well, NoSuchMethodException is normally well self-explaining. Unfortunately, in my case, I couldn't even guess why I am getting such error.
I am taking care a code from other developer and I must maintain it. It was designed with specification pattern in mind. In order to make the search engine very generic, basically, any string passed from client to rest service is split in order to build the search criteria.
When executing "clazzSpec.getDeclaredConstructor(SearchCriteria.class, String[].class).newInstance(param);" I get
java.lang.NoSuchMethodException: br.com.mycompany.specification.SomethingSpecification.<init>(br.com.mycompany.specification.SearchCriteria, [Ljava.lang.String;)
Looking the image bellow, I can't see what is missed
SearchCriteria:
public class SearchCriteria {
private String key;
private String operation;
private Object value;
public SearchCriteria(String key, String operation, Object value) {
this.key = key;
this.operation = operation;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getOperation() {
return operation;
}
public void setOperation(String operation) {
this.operation = operation;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
SomethingSpecification
public class SomethingSpecification extends Specification<Something> {
public SomethingSpecification(SearchCriteria criteria) {
super(criteria);
}
#Override
public Predicate toPredicate(Root<Something> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
switch (criteria.getOperation()) {
case "=":
...
}
return super.toPredicate(root, query, builder);
}
}
The reflection code looks for a constructor with two arguments: SearchCriteria and a String[]. But the only constructor for SomethingSpecification only has one argument.
I am about to start a small/medium sized project. I am by no means a software architect. But i tend to question every move i make at times. Since i want to do things correct.
I found a way to implement a simple repository, and i wanted to know if this is a "correct" way of doing it. I came to this solution, since i know what is going on, and not taking in something to complex before i have the knowledge :)
Here it goes.
Unit of work
Where i make sure i to keep all my repositories under the same dbcontext. In my uof i can access all repo's when calling it from the controller.
public class UnitOfWork : IDisposable
{
private ContactRepository _contactRepo;
private ApplicationDbContext _entities;
public UnitOfWork(ApplicationDbContext entities)
{
_entities = entities;
}
public ContactRepository ContactRepo
{
get
{
if (_contactRepo == null)
{
_contactRepo = new ContactRepository(_entities);
}
return _contactRepo;
}
}
public void Save()
{
_entities.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_entities.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
ContactRepository
This is a short example of a repository, where it recieves the dbcontext and uses it to grab whatever data i want
public class ContactRepository
{
private ApplicationDbContext _entities;
public ContactRepository(ApplicationDbContext entities)
{
_entities = entities;
}
public IEnumerable<Contact> GetAll()
{
return _entities.Contacts;
}
}
Controller
Short example of controller
public class ContactController : Controller
{
UnitOfWork uow = new UnitOfWork(new ApplicationDbContext());
public ActionResult Index()
{
var contacts = uow.ContactRepo.GetAll();
return View(contacts);
}
protected override void Dispose(bool disposing)
{
uow.Dispose();
base.Dispose(disposing);
}
}
In this way i will have access to all my repositories under the same dbcontext which i was aiming for.
I know things can be done smarter/different. With for example a extendable generic repo. But in this case i am aiming for something simple and understandable. But still dont want to make a huge mistake, if there is a major flaw.
Do you see any major flaws with this way of handling data trough entity framework?
If you're aiming for something simple then just use Entity Framework but if you're going to use the repository pattern I would encourage you to do it properly.
Two of the biggest motivators for using repository are:
You want to simplify CRUD applications to your database.This is
done through the use of interfaces and generics
You want to the ability to test the business logic in isolation
from external dependencies.Again, this is done through the use of
interfaces
Below will take you two minutes to implement but then at least you know you're doing it right, because at the moment you're trying to implement a great pattern in an ineffective way.
Generic interface:
public interface IRepository<T>
{
T GetById(int id);
IEnumerable<T> List();
IEnumerable<T> List(Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
void Update(T entity);
}
Generic repository:
public abstract class EntityBase
{
}
public class DBRepository<T> : IRepository<T> where T : EntityBase
{
private readonly DbContext _dbContext;
public DBRepository(DbContext dbContext)
{
_dbContext = dbContext;
}
public virtual T GetById(int id)
{
return _dbContext.Set<T>().Find(id);
}
public virtual IEnumerable<T> List()
{
return _dbContext.Set<T>().AsEnumerable();
}
public virtual IEnumerable<T> List(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
{
return _dbContext.Set<T>()
.Where(predicate)
.AsEnumerable();
}
public void Add(T entity)
{
_dbContext.Set<T>().Add(entity);
}
public void Update(T entity)
{
_dbContext.Entry(entity).State = EntityState.Modified;
}
public void Delete(T entity)
{
_dbContext.Set<T>().Remove(entity);
}
Unit of work:
public class UnitOfWork : IDisposable
{
private bool disposed = false;
private ApplicationDbContext context = new ApplicationDbContext();
private IRepository<Contact> _contactRepository;
public IRepository<Contact> ContactRepository
{
get
{
if (this._contactRepository == null)
this._contactRepository = new DBRepository<Contact>(context);
return _contactRepository;
}
}
public void Save()
{
context.SaveChanges();
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
context.Dispose();
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
I would like to understand why the variable IgnoreRequest is always false after setting it to true in my web api 2.2.
The filter:
public class RestrictToCandidatePlus : ActionFilterAttribute
{
public virtual bool IgnoreRequest { get; set; }
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
bool validAccType = 2 == 1; //original code hidden
if (!IgnoreRequest && !validAccType)
{
HandleUnauthorizedRequest(actionContext);
return;
}
base.OnActionExecuting(actionContext);
}
private void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
actionContext.Response = actionContext.Request.CreateResponse<String>(HttpStatusCode.Unauthorized, "Invalid account type");
}
}
And the controller:
[Filter1]
[Filter2]
[RestrictToCandidatePlus]
public class PlusCandidateController : ApiController
{
[RestrictToCandidatePlus(IgnoreRequest = true)]
[HttpPost]
public HttpResponseMessage SetInterest([FromBody] SetInterestModel model)
{
//some logic
return Request.CreateResponse(HttpStatusCode.OK);
}
}
I have exactly the same logic with the filters on my MVC5 application and it works like charm. I understand that filters in MVC are not the same used in the Web Api, but I think that I should be able to set the IgnoreRequest variable to true.
As you can see, I cannot use OverrideActionFiltersAttribute, otherwise it will disable Filter1 and Filter2, which is not what I want.
IgnoreRequest is always false because the controller level attribute is being evaluated first and you are error handling out before can evaluate the action attribute..
Instead of using a bool to override or block your attribute evaluation you can override the ActionFilterAttribute by using OverrideActionFiltersAttribute.
This will override any attribute inheriting from ActionFilterAttribute defined at the controller level.
Here is an updated attribute:
public class RestrictToCandidatePlus : ActionFilterAttribute
{
// dont need this
//public virtual bool IgnoreRequest { get; set; }
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
bool validAccType = 2 == 1; //original code hidden
//if (!IgnoreRequest && !validAccType)
if(!validAccType)
{
HandleUnauthorizedRequest(actionContext);
return;
}
base.OnActionExecuting(actionContext);
}
private void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
actionContext.Response = actionContext.Request.CreateResponse<String>(HttpStatusCode.Unauthorized, "Invalid account type");
}
}
Updated controller:
[RestrictToCandidatePlus]
public class PlusCandidateController : ApiController
{
[OverrideActionFiltersAttribute]// <== new attribute here
[HttpPost]
public HttpResponseMessage SetInterest([FromBody] SetInterestModel model)
{
//some logic
return Request.CreateResponse(HttpStatusCode.OK);
}
}
You can create your own attribute class inheriting from OverrideActionFiltersAttribute if you want to give it your own name like [OverrideCandidatePlus].
There is a great blog post here that explains how this works.
Note:
I have tested this with WebApi 2.2
I finally found the issue. The problem was that the same filter was running twice, starting from the Action (HttpResponseMessage) then the Controller. So if I set the IgnoreRequest = true in the controller level I could see the value set to true.
But the main problem was that the filter was running twice, so to fix this I had to override the following property:
public class RestrictToCandidatePlus : ActionFilterAttribute
{
public virtual bool IgnoreRequest { get; set; }
public override bool AllowMultiple { get { return false; } } // <= HERE!
public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
bool validAccType = 2 == 1; //original code hidden
if (!IgnoreRequest && !validAccType)
{
HandleUnauthorizedRequest(actionContext);
return;
}
base.OnActionExecuting(actionContext);
}
private void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext)
{
actionContext.Response = actionContext.Request.CreateResponse<String>(HttpStatusCode.Unauthorized, "Invalid account type");
}
}
I want to update a log file(txt) everytime when methods in a an interface class are called?
Is there any way to do this other than writing code in every method to create log?
Here's my 30 mins. you'll have to implement the logging code somewhere so you have to create another abstraction for your code. thus an abstract class is needed. i think. this is very quick and dirty.
public interface IService<T>
{
List<T> GetAll();
bool Add(T obj);
}
then you'll need the abstract class where you'll need to implement your logging routine
public abstract class Service<T> : IService<T>
{
private void log()
{
/// TODO : do log routine here
}
public bool Add(T obj)
{
try
{
log();
return AddWithLogging(obj);
}
finally
{
log();
}
}
public List<T> GetAll()
{
try
{
log();
return GetAllWithLog();
}
finally
{
log();
}
}
protected abstract List<T> GetAllWithLog();
protected abstract bool AddWithLogging(T obj);
}
as for your concrete classes
public class EmployeeService : Service<Employee>
{
protected override List<Employee> GetAllWithLog()
{
return new List<Employee>() { new Employee() { Id = 0, Name = "test" } };
}
protected override bool AddWithLogging(Employee obj)
{
/// TODO : do add logic here
return true;
}
}
public class CompanyService : Service<Company>
{
protected override List<Company> GetAllWithLog()
{
return new List<Company>() { new Company() { Id = 0, Name = "test" } };
}
protected override bool AddWithLogging(Company obj)
{
/// TODO : do add logic here
return true;
}
}
public class Employee
{
public int Id {get;set;}
public string Name { get; set;}
}
public class Company
{
public int Id { get; set; }
public string Name { get; set; }
}
then on your implementation you can just..
static void Main(string[] args)
{
IService<Employee> employee = new EmployeeService();
List<Employee> employees = employee.GetAll();
foreach (var item in employees)
{
Console.WriteLine(item.Name);
}
IService<Company> company = new CompanyService();
List<Company> companies = company.GetAll();
foreach (var item in companies)
{
Console.WriteLine(item.Name);
}
Console.ReadLine();
}
hope this helps!
I think you would have to use Aspect Oriented Programming to achieve that. Read http://www.sharpcrafters.com/aop.net
I think you meant class (instead of interface)
Two options I can think of:
Implementing INotifyPropertyChanged which is in lines of writing code in every method
or
to adopt on of the AOP frameworks in the article http://www.codeproject.com/KB/cs/AOP_Frameworks_Rating.aspx if that is not a major leap
I'm trying to setup the following:
/WebApplication
web.config
tokenlogin.aspx
/Services
web.config
AccessTokenService.svc
I put my WCF Service + configuration in the /WebApplication/Services folder.
This still workes as expected.
Now my AccessTokenService, which resides in an other assembly, expects an interface in its constructor called IAccessTokenRepository (see all code samples below).
Because normally WCF only allows for parameter-less constructors, I extended WCF using a custom IInstanceProvider, IServiceBehavior and BehaviorExtensionElement so Unity could resolve this for me.
As I did with the WCF configuration, I also put the Unity configuration inside the web.config file which resides in the Services folder. This way I don't pollute my web.config in my web app root. But that doesn't seem to work. I'm unable to read the unity configuration section from the web.config in the services folder. The GetSection part of the follwing code returns null:
public class UnityBehaviorExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(UnityServiceBehaviour); }
}
protected override object CreateBehavior()
{
UnityContainer unityContainer = new UnityContainer();
UnityConfigurationSection section = LoadUnitySection() as UnityConfigurationSection;
section.Containers.Default.Configure(unityContainer);
return new UnityServiceBehaviour(unityContainer);
}
private object LoadUnitySection()
{
if (System.Web.Hosting.HostingEnvironment.IsHosted)
return WebConfigurationManager.GetSection("unity");
return ConfigurationManager.GetSection("unity");
}
}
Now if I move the unity configuration to the web.config int the root of the WebApplication everything works fine. And I have no idea why.
The rest of the code:
[ServiceContract(Namespace = "http://services.xxx.com/AccessTokenService/1.0")]
public interface IAccessTokenService
{
[OperationContract]
Guid RequestAccessToken(AccessTokenRequest accessTokenRequest);
}
public class AccessTokenService : IAccessTokenService
{
private readonly IAccessTokenRepository accessTokenRepository;
public AccessTokenService(IAccessTokenRepository accessTokenRepository)
{
if (accessTokenRepository == null)
throw new ArgumentNullException("accessTokenRepository");
this.accessTokenRepository = accessTokenRepository;
}
public Guid RequestAccessToken(AccessTokenRequest accessTokenRequest)
{
return accessTokenRepository.Store(accessTokenRequest);
}
}
public class UnityInstanceProvider : IInstanceProvider
{
private readonly Type serviceType;
private readonly UnityContainer unityContainer;
public UnityInstanceProvider(Type serviceType, UnityContainer unityContainer)
{
this.serviceType = serviceType;
this.unityContainer = unityContainer;
}
#region IInstanceProvider Members
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
return unityContainer.Resolve(serviceType);
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
if (instance == null)
return;
if (instance is IDisposable)
((IDisposable)instance).Dispose();
}
#endregion
}
public class UnityServiceBehaviour : IServiceBehavior
{
private readonly UnityContainer unityContainer;
public UnityServiceBehaviour(UnityContainer unityContainer)
{
this.unityContainer = unityContainer;
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (var channel in serviceHostBase.ChannelDispatchers.OfType())
{
if (channel == null)
continue;
foreach (var endPointDispatcher in channel.Endpoints)
{
endPointDispatcher.DispatchRuntime.InstanceProvider =
new UnityInstanceProvider(serviceDescription.ServiceType, unityContainer);
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}