I have created a web service with ServiceStack which returns List<SyncUserDTO>.
It has more properties, but I simplified it to one field, Timestamp.
[DataContract]
public class SyncUserDTO
{
public SyncUserDTO()
{
Timestamp = new TimestampDTO();
}
[DataMember(Order = 1)]
public TimestampDTO Timestamp { get; set; }
}
[DataContract]
public class TimestampDTO
{
[DataMember]
public bool DataValid { get; set; }
[DataMember]
public DateTime? Value { get; set; }
}
The service seems to work perfectly (with other tests), but when I create a client console application and Add Service Reference, the SyncUserDTO does not have the constructor, meaning this doesn't work:
static void SendUsersServiceReference()
{
var users = new List<SyncUserDTO>();
for (var i = 0; i < 5; i++)
{
var user = new SyncUserDTO();
user.Timestamp.Value = DateTime.Now; // NullReferenceException,
user.Timestamp.DataValid = true; // as Timestamp is null
}
}
When pressing F12 on SyncUserDTO, I can't seem to find any Constructor method in Reference.cs, explaining why the above doesn't work.
But why is the constructor not created in my proxy classes in the client application?
I need to do the "construction" myself in the client, and then it works:
var user = new SyncUserDTO() { Timestamp = new TimestampDTO() };
Of cause, I don't want the people who consumes my service to have to create this themselves. They should really note care about the underlying TimestampDTO. The constructor should do this.
Btw, I searched Google and SO for terms like "Constructor not created in proxy class with Add Service Reference" with and without "ServiceStack", no results to aid me in this quest...
Pps. Demis (ServiceStack), if you're reading this, yes SOAP is on the way out, REST is the new black - but I want to support both, which it seems like ServiceStack does, which is really great. I love ServiceStack :D
try to instanciate your property by the time you are going to access it, I know that´s a workaround but it could be convenient in your scenario.
private TimestampDTO _timestamp;
public TimestampDTO Timestamp
{
get
{
if(_timestamp==null) _timestamp=new TimestampDTO();
return _timestamp;
}
set
{
_Timestamp=value;
}
}
This is my solution (for now):
I created a new service method in my service, where the client gets a new UserDTO complete with all fields. This way, the constructor is run on the server. I bet I have quite a performance hit this way, but it doesn't matter that much (now...).
Service DTO's:
[DataContract]
public class ReturnNewEmptyUser : IReturn<ReturnNewEmptyUserResponse> {}
[DataContract]
public class ReturnNewEmptyUserResponse
{
[DataMember]
public SyncUserDTO User { get; set; }
}
The Service:
public class SyncService : Service
{
public ReturnNewEmptyUserResponse Any(ReturnNewEmptyUser request)
{
var user = new ReturnNewEmptyUserResponse { User = new SyncUserDTO() };
return user;
}
}
On the client:
static void SendUsersServiceReference()
{
var webservice = new ServiceReference1.SyncReplyClient();
var users = new List<User>();
for (var i = 0; i < 5; i++)
{
var userResponse = webservice.ReturnNewEmptyUser(new ReturnNewEmptyUser());
var user = userResponse.User;
user.Timestamp.Value = DateTime.Now;
user.Timestamp.DataValid = true;
// Continue with field population...
users.Add(user);
}
// Send users with webservice method
// ...
}
We're wondering if it is a bad way to expose the fields this way. It is nice, because the client can use autocomplete and know exactly the types used - but is it better to force the client to create an XML/JSON in a specific format.
This should be in another question - this question I guess has been answered: Add service reference/proxy classes does not contain methods (incl. constructors for types), only types. If you really need the constructor, have it run and then exposed on the server and then consume it from the client. Like a factory-thing, as Adam wrote here: Class constructor (from C# web service) won't auto-implement properties in C# MVC
Btw - is there any security issues with this design? User is logged in via url-credentials (should probably be header authentication), only a few systems has access to it.
A proxy class does not keep implementation details, like a constructor. It is just a DTO. This can only be done if you share the classes, through a shared project.
Think about that servicestack is just telling the client which properties it needs, and their type.. the implementation is up to the client.
Related
I am developing a web application in ASP.NET MVC5.
Like all basic web applications it also has a login page where a user can authenticate himself. Once authenticated I want to store a couple of user-related items in the Session so I don't have to query the database every time to reconstruct the authenticated user.
After having read Mark Seemann's book about Dependency Injection I want to loosely couple all my layers and make sure that everything can easily be replaced.
At the moment my SessionProvider is by default using the Session object, but maybe in the future this could change to another type of storage mechanism.
The approach I have taken is by using Ambient Context which he explained with the TimeProvider example, but I am wondering if this is the right approach for this functionality and if it is thread safe (also for unit testing).
Is my solution proper or how would you implement such a mechanism? This has been in my head for days now so who can help me define the best solution?
Thanks!
public abstract class SessionProvider
{
private static SessionProvider _current;
static SessionProvider()
{
_current = new DefaultSessionProvider();
}
public static SessionProvider Current
{
get { return _current; }
set
{
if (value == null)
{
throw new ArgumentNullException();
}
_current = value;
}
}
public abstract string UserName { get; set; }
}
My local default:
public class DefaultSessionProvider : SessionProvider
{
public override string UserName
{
get { return (string) HttpContext.Current.Session["username"]; }
set { HttpContext.Current.Session["username"] = value; }
}
}
So I have access in my entire solution to my SessionProvider, whether this is a real session object or a database-driven storage mechanism...
SessionProvider.Current.UserName = "myUserName";
Once authenticated I want to store a couple of user-related items in
the Session so I don't have to query the database every time to
reconstruct the authenticated user.
Well, it looks like you're working on some sort of caching mechanism. It doesn't really matter if it's in a Session or in Redis cache, or any other type of cache. And this cache is key-value storage. I would create cache interface, something like that:
interface ICache
{
object this[string key] {get; set;}
}
And create concrete classes. SessionCache in your case:
public SessionCache : ICache
{
private IHttpSessionState _session;
public SessionCache(IHttpSessionState session)
{
_session = session;
}
// ICache implementation goes here...
}
So you'll narrow down the problem to dependency-inject Session object to concrete class (SessionCache). With Ninject you can do something like:
.WithConstructorArgument("session",ninjectContext=>HttpContext.Session);
And after that you can finally make your controllers dependent on ICache.
In your unit tests project you can create another ICache concrete class, something like DummyCache with in-memory cache. So you can test your controllers without sticking to Session object.
I twist myself around a workable solution to use several databases in RavenDB for an ASP.Net MVC app using Castle Windsor for the wiring.
This is the current installer
public class RavenInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IDocumentStore>().Instance(CreateDocumentStore()).LifeStyle.Singleton,
Component.For<IDocumentSession>().UsingFactoryMethod(GetDocumentSesssion).LifeStyle.PerWebRequest
);
}
static IDocumentStore CreateDocumentStore()
{
var store = new DocumentStore { ConnectionStringName = "RavenDb_CS9" };
store.Initialize();
IndexCreation.CreateIndexes(typeof(Users).Assembly, store);
return store;
}
static IDocumentSession GetDocumentSesssion(IKernel kernel)
{
var store = kernel.Resolve<IDocumentStore>();
return store.OpenSession();
}
}
The above works perfect but only for one Database.
I can't find the proper thinking how to handle another database. The whole chain starts with a domain service asking for an IDocumentSession. Then the flow is as specified in the above installer. But where/how do I ask for a "SessionToDb1" or a "SessionToDb2"?
The important is of course what connection string to use (where the DB property is specified) but also what indexes to create in respective DB / DocumentStore.
Did anyone accomplish this using Windsor? Am I thinking/attacking it wrong here?
Thanks!
Because you have:
Component.For<IDocumentSession>()
.UsingFactoryMethod(GetDocumentSesssion)
.LifeStyle.PerWebRequest
Your GetDocumentSession method is going to be called any time you inject an IDocumentSession. This is good.
When working with multiple databases, you need to pass the database name as a parameter to OpenSession. So, you need some way to resolve which database you would like to connect to based on the current web request.
You need to modify the GetDocumentSession method to implement whatever custom logic you are going to use. For example, you may want to look at a cookie, asp.net session item, current thread principal, or some other criteria. The decision is custom to your application, all that matters is somehow you open the session with the correct database name.
I've run into this problem before with nhibernate.
I found the best solution is to create a SessionManager class which wraps the Creation of the document store and the Session..
So I.E.
public interface ISessionManager
{
void BuildDocumentStore();
IDocumentSession OpenSession();
}
public interface ISiteSessionManager : ISessionManager
{
}
public class SiteSessionManager : ISiteSessionManager
{
IDocumentStore _documentStore;
public SiteSessionManager()
{
BuildDocumentStore();
}
public void BuildDocumentStore()
{
_documentStore = new DocumentStore
{
Url = "http://localhost:88",
DefaultDatabase = "test"
};
_documentStore.Initialize();
IndexCreation.CreateIndexes(typeof(SiteSessionManager).Assembly, _documentStore);
}
public IDocumentSession OpenSession()
{
return _documentStore.OpenSession();
}
}
// And then!.
Container.Register(Component.For<ISiteSessionManager>().Instance(new SiteSessionManager()).LifestyleSingleton());
// And then!.
public class FindUsers
{
readonly ISiteSessionManager _siteSessionManager;
public FindUsers(ISiteSessionManager siteSessionManager)
{
_siteSessionManager = siteSessionManager;
}
public IList<User> GetUsers()
{
using (var session = _siteSessionManager.OpenSession())
{
// do your query
return null;
}
}
}
Rinse and repeat for multiple databases.!
I am new to ASP.NET MVC. I have used PHP before and it was easy to create a session and select user records based on the current session variables.
I have looked everywhere on the Internet for a simple step-by-step tutorial that can show me how to create and use sessions in my C# ASP.NET MVC 4 application. I want to create a session with user variables that I can access from anywhere in my controllers and be able to use the variables in my LINQ queries.
Try
//adding data to session
//assuming the method below will return list of Products
var products=Db.GetProducts();
//Store the products to a session
Session["products"]=products;
//To get what you have stored to a session
var products=Session["products"] as List<Product>;
//to clear the session value
Session["products"]=null;
Due to the stateless nature of the web, sessions are also an extremely useful way of persisting objects across requests by serialising them and storing them in a session.
A perfect use case of this could be if you need to access regular information across your application, to save additional database calls on each request, this data can be stored in an object and unserialised on each request, like so:
Our reusable, serializable object:
[Serializable]
public class UserProfileSessionData
{
public int UserId { get; set; }
public string EmailAddress { get; set; }
public string FullName { get; set; }
}
Use case:
public class LoginController : Controller {
[HttpPost]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
var profileData = new UserProfileSessionData {
UserId = model.UserId,
EmailAddress = model.EmailAddress,
FullName = model.FullName
}
this.Session["UserProfile"] = profileData;
}
}
public ActionResult LoggedInStatusMessage()
{
var profileData = this.Session["UserProfile"] as UserProfileSessionData;
/* From here you could output profileData.FullName to a view and
save yourself unnecessary database calls */
}
}
Once this object has been serialised, we can use it across all controllers without needing to create it or query the database for the data contained within it again.
Inject your session object using Dependency Injection
In a ideal world you would 'program to an interface, not implementation' and inject your serializable session object into your controller using your Inversion of Control container of choice, like so (this example uses StructureMap as it's the one I'm most familiar with).
public class WebsiteRegistry : Registry
{
public WebsiteRegistry()
{
this.For<IUserProfileSessionData>().HybridHttpOrThreadLocalScoped().Use(() => GetUserProfileFromSession());
}
public static IUserProfileSessionData GetUserProfileFromSession()
{
var session = HttpContext.Current.Session;
if (session["UserProfile"] != null)
{
return session["UserProfile"] as IUserProfileSessionData;
}
/* Create new empty session object */
session["UserProfile"] = new UserProfileSessionData();
return session["UserProfile"] as IUserProfileSessionData;
}
}
You would then register this in your Global.asax.cs file.
For those that aren't familiar with injecting session objects, you can find a more in-depth blog post about the subject here.
A word of warning:
It's worth noting that sessions should be kept to a minimum, large sessions can start to cause performance issues.
It's also recommended to not store any sensitive data in them (passwords, etc).
This is how session state works in ASP.NET and ASP.NET MVC:
ASP.NET Session State Overview
Basically, you do this to store a value in the Session object:
Session["FirstName"] = FirstNameTextBox.Text;
To retrieve the value:
var firstName = Session["FirstName"];
You can store any kind of data in a session using:
Session["VariableName"]=value;
This variable will last 20 mins or so.
U can store any value in session like
Session["FirstName"] = FirstNameTextBox.Text;
but i will suggest u to take as static field in model assign value to it and u can access that field value any where in application. U don't need session. session should be avoided.
public class Employee
{
public int UserId { get; set; }
public string EmailAddress { get; set; }
public static string FullName { get; set; }
}
on controller - Employee.FullName = "ABC";
Now u can access this full Name anywhere in application.
I am using Entity framework 5 and using repository pattern. Say I got these entities Customer, Files, Images, Tasks, Invoice, User.
Each entity (apart from Customer) has a foreign key of Customer. When a user logs in I store the customerid in session (aps.net mvc). What I want is any CRUD taken on all entities to be limited to the customer who's user is logged in. e.g I can't afford to delete a Task belonging to customer 1 to be deleted by user who is from customer 2.
Is adding an argument of customerid for each method of repositories the best way to achieve this or are there any better/clever ways of doing it?
Tricky to give a definitive answer but you could make it a bit more extensible by implementing higer order functions, like this:
public interface IRepository<T>
{
public T GetBy(Expression<Func<T, bool>> query)
}
public class FileRepository : IRepository<File>
{
public File GetBy(Expression<Func<T, bool>> query)
{
using(var context = new FilesContext())
{
return context.Files.Where(query).FirstOrDefault();
}
}
}
public class SomeController
{
private IRepository<File> _repo;
public SomeController(IRepository<File> repo)
{
_repo = repo;
}
public ActionResult Index()
{
var model = _repo.GetBy(f => f.CustomerId == Session.Whatever.CustomerId);
return View(model);
}
}
This way you can vary the search query when required, rather than tie yourself in to using a hardcoded customer id property. For example, if you wanted to get the File object by the FileID, not the CustomerID, then:
var model = _repo.GetBy(f => f.FileId == someId);
and that's the only part of the code that needs to change.
Some really good info on Higher Order functions and functional programming in C# here: http://www.codeproject.com/Articles/375166/Functional-programming-in-Csharp
Edit:
You might be able to isolate the "Always use the customer ID when hitting DB" into a repository of it's own, using a decorator style pattern, thus: (massive disclaimer - I haven't tested this, but something along these lines should work)
public class SpecialFileRepo : IRepository<File>
{
private readonly IRepository<File> _baseRepo;
public SpecialFileRepo(IRepository<File> baseRepo)
{
_baseRepo = baseRepo;
}
public SpecialFileRepo() : this(new FileRepository())
{
}
public File GetBy(Expression<Func<File, bool>> query)
{
var parameters = query.Parameters;
var newParam = Expression.Parameter(typeof (File), "f");
var additionalQuery = Expression.AndAlso(query.Body,
Expression.Equal(
Expression.PropertyOrField(newParam, "CustomerId"),
Expression.Constant(HttpContext.Current.Session["customerId"])));
var newQuery = query.Update(additionalQuery, parameters);
return _baseRepo.GetBy(newQuery);
}
}
Then anything that's talking to a repository, as far as it's concerned, it's just a base repository, but this class is sitting in between and always grafting the "customerid = sessionwhatever" expression onto what finally gets passed to the database. And of course, anything that only cares about using the base repository, can still do so.
Description
My solution has these projects:
DAL = Modified Entity Framework
DTO = Data Transfer objects that are able to validate themselves
BL = Business Layer Services
WEB = presentation Asp.net MVC application
DAL, BL and WEB all reference DTO which is great.
The process usually executes this way:
A web request is made to the WEB
WEB gets DTOs posted
DTOs get automagically validated via custom ActionFilter
validation errors are auto-collected
(Validation is OK) WEB calls into BL providing DTOs
BL calls into DAL by using DTOs (can either pass them through or just use them)
DTO Validation problem then...
My DTOs are able to validate themselves based on their own state (properties' values). But right now I'm presented with a problem when this is not the case. I need them to validate using BL (and consequently DAL).
My real-life example: User registers and WEB gets a User DTO that gets validated. The problematic part is username validation. Its uniqueness should be checked against data store.
How am I supposed to do this?
There's additional info that all DTOs implement an interface (ie. User DTO implements IUser) for IoC purposes and TDD. Both are part of the DTO project.
Impossible tries
I can't reference BL in DTO because I'll get circular reference.
Compilation error
I can't create an additional DTO.Val project that would reference partial DTO classes and implement their validation there (they'd reference BL + DTO).
Partial classes can't span assemblies.
Possible tries
Create a special ActionFilter that would validate object against external conditions. This one would be created within WEB project thus seeing DTO and BL that would be used here.
Put DTOs in BL and keep DTO interfaces as actual DTOs referenced by other projects and refactor all code to use interfaces instead of concrete classes.
Don't handle external dependant validation and let external dependencies throw an exception - probably the worst solution to this issue
What would you suggest?
I would suggest an experiment that i have only been trialling for the last week or so.
Based on this inspiration i am creating DTOs that validate a little differently to that of the DataAnnotations approach. Sample DTO:
public class Contact : DomainBase, IModelObject
{
public int ID { get; set; }
public string Name { get; set; }
public LazyList<ContactDetail> Details { get; set; }
public DateTime Updated { get; set; }
protected override void ConfigureRules()
{
base.AddRule(new ValidationRule()
{
Properties = new string[] { "name" },
Description = "A Name is required but must not exceed 300 characters in length and some special characters are not allowed",
validator = () => this.Name.IsRequired300LenNoSpecial()
});
base.AddRule(new ValidationRule()
{
Properties = new string[] { "updated" },
Description = "required",
validator = () => this.Updated.IsRequired()
});
}
}
This might look more work than DataAnnotations and well, that's coz it is, but it's not huge. I think it's more presentable in the class (i have some really ugly DTO classes now with DataAnnotations attributes - you can't even see the properties any more). And the power of anonymous delegates in this application is almost book-worthy (so i'm discovering).
Base class:
public partial class DomainBase : IDataErrorInfo
{
private IList<ValidationRule> _rules = new List<ValidationRule>();
public DomainBase()
{
// populate the _rules collection
this.ConfigureRules();
}
protected virtual void ConfigureRules()
{
// no rules if not overridden
}
protected void AddRule(ValidationRule rule)
{
this._rules.Add(rule);
}
#region IDataErrorInfo Members
public string Error
{
get { return String.Empty; } // Validation should call the indexer so return "" here
} // ..we dont need to support this property.
public string this[string columnName]
{
get
{
// get all the rules that apply to the property being validated
var rulesThatApply = this._rules
.Where(r => r.Properties.Contains(columnName));
// get a list of error messages from the rules
StringBuilder errorMessages = new StringBuilder();
foreach (ValidationRule rule in rulesThatApply)
if (!rule.validator.Invoke()) // if validator returns false then the rule is broken
if (errorMessages.ToString() == String.Empty)
errorMessages.Append(rule.Description);
else
errorMessages.AppendFormat("\r\n{0}", rule.Description);
return errorMessages.ToString();
}
}
#endregion
}
ValidationRule and my validation functions:
public class ValidationRule
{
public string[] Properties { get; set; }
public string Description { get; set; }
public Func<bool> validator { get; set; }
}
/// <summary>
/// These extention methods return true if the validation condition is met.
/// </summary>
public static class ValidationFunctions
{
#region IsRequired
public static bool IsRequired(this String str)
{
return !str.IsNullOrTrimEmpty();
}
public static bool IsRequired(this int num)
{
return num != 0;
}
public static bool IsRequired(this long num)
{
return num != 0;
}
public static bool IsRequired(this double num)
{
return num != 0;
}
public static bool IsRequired(this Decimal num)
{
return num != 0;
}
public static bool IsRequired(this DateTime date)
{
return date != DateTime.MinValue;
}
#endregion
#region String Lengths
public static bool IsLengthLessThanOrEqual(this String str, int length)
{
return str.Length <= length;
}
public static bool IsRequiredWithLengthLessThanOrEqual(this String str, int length)
{
return !str.IsNullOrTrimEmpty() && (str.Length <= length);
}
public static bool IsRequired300LenNoSpecial(this String str)
{
return !str.IsNullOrTrimEmpty() &&
str.RegexMatch(#"^[- \r\n\\\.!:*,#$%&""?\(\)\w']{1,300}$",
RegexOptions.Multiline) == str;
}
#endregion
}
If my code looks messy well that's because i've only been working on this validation approach for the last few days. I need this idea to meet a few requirements:
I need to support the IDataErrorInfo interface so my MVC layer validates automatically
I need to be able to support complex validation scenarios (the whole point of your question i guess): I want to be able to validate against multiple properties on the same object (ie. StartDate and FinishDate); properties from different/multiple/associated objects like i would have in an object graph; and even other things i haven't thought of yet.
I need to support the idea of an error applying to more than one property
As part of my TDD and DDD journey i want my Domain Objects to describe more my 'domain' than my Service layer methods, so putting these complex conditions in the model objects (not DTOs) seems to achieve this
This approach i think will get me what i want, and maybe you as well.
I'd imagine if you jump on board with me on this that we'd be pretty 'by ourselves' but it might be worth it. I was reading about the new validation capabilities in MVC 2 but it still doesn't meet the above wish list without custom modification.
Hope this helps.
The S#arp Architecture has an [DomainSignature] method identifier that used with the class level validator [HasUniqueDomainSignature] will do the work. See the sample code below:
[HasUniqueDomainSignature]
public class User : Entity
{
public User()
{
}
public User(string login, string email) : this()
{
Login = login;
Email = email;
}
[DomainSignature]
[NotNullNotEmpty]
public virtual string Login { get; set; }
[DomainSignature]
public virtual string Email { get; set; }
}
Take a closer look at http://www.sharparchitecture.net/
I had this exact same problem and after trying to find a work around for days and days and days, I ended up merging my DTO, DAL, and BL into one library. I kept my presentation layer separate.
Not sure if that is an option for you or not. For me, I figured that my chances of ever changing the data store were very slight, and so the separate tier wasn't really needed.
I also have implemented the Microsoft Validation Application Block for all my DTO validations. They have a "Self Validation" method that lets you perform complex validations.
Resulting solution
I ended up using controller action filter that was able to validate object against external factors that can't be obtained from the object itself.
I created the filter that takes the name of the action parameter to check and validator type that will validate that particular parameter. Of course this validator has to implement certain interface to make it all reusable.
[ValidateExternalFactors("user", typeof(UserExternalValidator))]
public ActionResult Create(User user)
validator needs to implement this simple interface
public interface IExternalValidator<T>
{
bool IsValid(T instance);
}
It's a simple and effective solution to a seemingly complex problem.