I'm looking for an elegant way to have AppContext configured right and here is it:
public class AppContext : IAppContext
{
public AppContext()
{
Application = new AppStorage(); // app scoped hashtable
Local = new LocalStorage(); // current thread scoped hashtable
Session = new SessionStorage(); // session for some reasons hashtable
}
public CultureInfo Culture { get; set; } // session scoped
public UserProfile AuthProfile { get; set; } // session scoped
public IStorage Application { get; private set; } // application
public IStorage Session { get; private set; } // session
public IStorage Local { get; private set; } // current thread
public IStorage WcfSession { get; private set; } // wcf session
private ISecurityWriter SecurityWriter; // session scoped
private ISecurityContext SecurityContext; // session scoped
/// 1. START WEB CONTEXT
/// 2. START WCF CONTEXT
}
currently I am balancing between
a)
public class Global : HttpApplication
{
public static AppContext Context;
protected void Application_Start(object sender, EventArgs e)
{
Context = new AppContext();
}
}
but I don't like the ideea to have
Global.Context.Sesstion.Set<Order>(theOrderInstance);
b) and the addition to AppContext following lines
public class AppContext{
private static AppContext instance;
public AppContext Instance
{
get{
if(instance == null)
instance = new AppContext();
return instance;
}
}
this also is not nice looking
AppContext.Instance.Session.Set<Order>(theOrderInstance);
QUESTION: I like the idea of having
AppContext.Session.Set<Order>(theOrderInstance);
any toughs how to achieve this ?
something OSS and relevant for this topic would be greatly appreciated
have fun :)
How about this way?
protected AppContext Instance
{
get{
if(instance == null)
instance = new AppContext();
return instance;
}
}
public IStorage Session
{
get{
return Instance.Session;
}
}
look here:
public static class AppContextExtensions
{
public static AppContext Context(this Page page)
{
return AppContext.Instance;
}
}
usage
this.Context().Session.Set<Order>(theOrderInstance)
and i'm happy with it :)
Related
This is Razor form code
#inherits OwningComponentBase<SignatureColoursServices>
List Displaydata=new List();
protected override void OnInitialized()
{
Displaydata = Service.GetSignatures();
}
This is the code in Startup.cs:
services.AddSingleton<ISignatureColoursServices,SignatureColoursServices>();
This is SignatureColour.cs
public string Value { get; set; } = null!;
public string Description { get; set; } = null!;
This is signaturecolourservices.cs:
protected readonly MyDbContext _dbcontext;
public SignatureColoursServices(MyDbContext db)
{
_dbcontext = db;
}
public List<SignatureColour> GetSignatures()
{
return _dbcontext.SignatureColours.ToList();
}
I have tried adding singleton and transient and scoped in startup.cs
You needed to register the service properly. Register SignatureColourServices in the Program.cs file. Please check the below example.
builder.Services.AddScoped<IEmployeeService, EmployeeService>();
builder.Services.AddScoped<ICustomerService, CustomerService>();
builder.Services.AddScoped<SignatureColourServices>();
TLDR: In Asp Mvc 6 how do I perform model validation with a service using data annotations? What are the alternatives?
I have a very simple model
public class MyModel
{
[Required]
public string Name { get; set; }
}
I also have a service that exposes some simple validation methods
public interface IMyService
{
string[] ReservedWords { get; }
bool IsValidName(string name);
// Internally calls IsValidName and throws an Exception if the name is invalid
void Save(MyModel myModel);
// ... snip
}
And I have wired up my controller like so
public class MyController : Controller
{
private readonly IMyService _service;
public MyController(IMyService service)
{
_service = service;
}
// ... snip
public IActionResult Post(MyModel myModel)
{
if (!_service.IsValidName(input?.Name))
{
ModelState.AddModelError(nameof(MyModel.Name), "Invalid Name");
}
if (!ModelState.IsValid)
{
return View(myModel);
}
_service.Save(myModel);
return RedirectToAction(nameof(Index));
}
}
It feels a bit clucky to have 2 stages of validation - automatic model validation then manually performing service validation. I was hoping that something simialr to this would work
public class MyModel
{
[ServiceValidation(nameof(IMyService), nameof(IMyService.IsValidName)]
[Required]
public string Name { get; set; }
}
public ServiceValidationAttribute : ValidationAttribute
{
private readonly Type _interfaceOrClass;
private readonly string _methodOrProperty;
public ServiceValidationAttribute(Type interfaceOrClass, string methodOrProperty)
{
_interfaceOrClass = interfaceOrClass;
_methodOrProperty = methodOrProperty;
}
public override bool RequiresValidationContext => true;
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var service = validationContext.GetService(_interfaceOrClass);
// Extension method in shared library to assist with reflection
bool isValid = _interfaceOrClass.ValueForMethodOrPropertyNamed<bool>(service, _methodOrProperty, value);
return isValid
? ValidationResult.Success
: new ValidationResult(ErrorMessage);
}
}
However var serivce is always null, is there any way around this? I have wired up the IMyService to an implementation in the Startup.cs as it is available in the Controller.
Alternatively is there a better way of adding to the ModelState with a service?
I am using ASP.NET EntityFramework MVC (All Latest) with Visual Studio 2013.
I am attempting to come up with a unifying means of standardizing the abstraction between my object and data layer.
I know that many people like to use the IRepository pattern with MVC. My biggest issue with this is that it forces you to create and maintain a second object type (The Repository) for each of the objects that you want to maintain. My solution has been to combing the IRepository method with a Static Factory pattern to make a Static Repository, for instance:
public class SiteDatabase : DbContext
{
// Singleton
private static SiteDatabase _Instance;
public static SiteDatabase Instance
{
get
{
if (_Instance == null)
{
_Instance = new SiteDatabase();
}
return _Instance;
}
}
public DbSet<User> Users { get; set; }
}
public class User : IUser
{
public static User Create(string UserName)
{
User item = new User();
item.UserName = UserName;
SiteDatabase.Instance.Users.Add(item);
return item;
}
public static User Find(string UserName)
{
return SiteDatabase.Instance.Users.SingleOrDefault(x => x.UserName == UserName);
}
public static User[] All()
{
return SiteDatabase.Instance.Users.ToArray();
}
public string Id { get; set; }
public string UserName { get; set; }
protected User()
{
Id = Guid.NewGuid().ToString();
}
public void Delete()
{
SiteDatabase.Instance.Users.Remove(this);
}
}
public class Page
{
public static Page Create(string PageName)
{
...
}
public static Page Find(string PageName)
{
...
}
public static Page[] All()
{
...
}
...
public void Delete()
{
...
}
}
My question is: will this pattern cause me to miss out on any built-in functionality that the normal repository pattern would allow me to capture?
The non-static methods could be handled with an interface, but what about the static methods? Is there any way to have a base class that ensures that static methods will exist in derived classes?
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 implement the state pattern for a multi-page registration form. The data on each page will be accumulated and stored in a session object.
Should validation (including service layer calls to the DB) occur on the page level or inside each state class? In other words, should the concrete implementation of IState be concerned with the validation or should it be given a fully populated and valid object? See "EmptyFormState" class below:
namespace Example
{
public class Registrar
{
private readonly IState formEmptyState;
private readonly IState baseInformationComplete;
public RegistrarSessionData RegistrarSessionData { get; set;}
public Registrar()
{
RegistrarSessionData = new RegistrarSessionData();
formEmptyState = new EmptyFormState(this);
baseInformationComplete = new BasicInfoCompleteState(this);
State = formEmptyState;
}
public IState State { get; set; }
public void SubmitData(RegistrarSessionData data)
{
State.SubmitData(data);
}
public void ProceedToNextStep()
{
State.ProceedToNextStep();
}
}
//actual data stored in the session
//to be populated by page
public class RegistrarSessionData
{
public string FirstName { get; set; }
public string LastName { get; set; }
//will include values of all 4 forms
}
//State Interface
public interface IState
{
void SubmitData(RegistrarSessionData data);
void ProceedToNextStep();
}
//Concrete implementation of IState
//Beginning state - no data
public class EmptyFormState : IState
{
private readonly Registrar registrar;
public EmptyFormState(Registrar registrar)
{
this.registrar = registrar;
}
public void SubmitData(RegistrarSessionData data)
{
//Should Validation occur here?
//Should each state object contain a validation class? (IValidator ?)
//Should this throw an exception?
}
public void ProceedToNextStep()
{
registrar.State = new BasicInfoCompleteState(registrar);
}
}
//Next step, will have 4 in total
public class BasicInfoCompleteState : IState
{
private readonly Registrar registrar;
public BasicInfoCompleteState(Registrar registrar)
{
this.registrar = registrar;
}
public void SubmitData(RegistrarSessionData data)
{
//etc
}
public void ProceedToNextStep()
{
//etc
}
}
}
I prefer to validate at both the state (collection) level AND the final commit. In general, I prefer to validate as soon as possible as part of a good user experience. From a data validation/protection level I prefer to validate at the final save/commit level as well just in case something snuck through, protection against generall trickery, or (more likely) a different route to the save/commit point in the future.