MVC 6 Identity ChangePassword for "SuperUser" - asp.net-mvc

I need for "SuperUser" ability to change password of any user in identity system. I checked two solution.
1) add this one overloaded function to CustomUserManager for CRUD:
public async Task<IdentityResult> ChangePasswordAsync(TenantUser user, string newPassword)
{...}
Use original function with token parameter, but this function in controller not working and return invalid token:
string Token = await manager.GeneratePasswordResetTokenAsync(TenantUser);
var resultPasswordChange = await manager.ResetPasswordAsync(TenantUser, Token, model.TenantUsersPassword.Password);
Custom user manager: All PRIVATE functions and parameters has been already copied from orig UserManager to derived CustomUserManager. Resources for NotSupportedException are still not available... I'm not satisfacted with result...
Can you help me? What is better? Implement CustomUserManager or solve invalid token error? And please how to do?
Example what you need to copy for one more function (ChangePasswordAsync):
namespace Program.Models
{
public class TenantUserManager<TenantUser> : UserManager<TenantUser>, IDisposable where TenantUser : class
{
// protected const string ResetPasswordTokenPurpose = "ResetPassword";
// protected const string ConfirmEmailTokenPurpose = "EmailConfirmation";
private TimeSpan _defaultLockout = TimeSpan.Zero;
private bool _disposed;
private readonly HttpContext _context;
private CancellationToken CancellationToken => _context?.RequestAborted ?? CancellationToken.None;
/// <summary>
/// Constructs a new instance of <see cref="UserManager{TenantUser}"/>.
/// </summary>
/// <param name="store">The persistence store the manager will operate over.</param>
/// <param name="optionsAccessor">The accessor used to access the <see cref="IdentityOptions"/>.</param>
/// <param name="userValidators">A collection of <see cref="IUserValidator{TenantUser}"/> to validate users against.</param>
/// <param name="passwordValidators">A collection of <see cref="IPasswordValidator{TenantUser}"/> to validate passwords against.</param>
/// <param name="keyNormalizer">The <see cref="ILookupNormalizer"/> to use when generating index keys for users.</param>
/// <param name="errors">The <see cref="IdentityErrorDescriber"/> used to provider error messages.</param>
/// <param name="services">The <see cref="IServiceProvider"/> used to resolve services.</param>
public TenantUserManager(IUserStore<TenantUser> store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TenantUser> passwordHasher, IEnumerable<IUserValidator<TenantUser>> userValidators,
IEnumerable<IPasswordValidator<TenantUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<TenantUser>> logger, IHttpContextAccessor contextAccessor)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger, contextAccessor)
{
}
/// <summary>
/// Gets or sets the persistence store the manager operates over.
/// </summary>
/// <value>The persistence store the manager operates over.</value>
protected internal IUserStore<TenantUser> Store { get; set; }
/// <summary>
/// Gets the <see cref="ILogger"/> used to log messages from the manager.
/// </summary>
/// <value>
/// The <see cref="ILogger"/> used to log messages from the manager.
/// </value>
// protected internal virtual ILogger Logger { get; set; }
internal IPasswordHasher<TenantUser> PasswordHasher { get; set; }
internal IList<IUserValidator<TenantUser>> UserValidators { get; } = new List<IUserValidator<TenantUser>>();
internal IList<IPasswordValidator<TenantUser>> PasswordValidators { get; } = new List<IPasswordValidator<TenantUser>>();
internal ILookupNormalizer KeyNormalizer { get; set; }
internal IdentityErrorDescriber ErrorDescriber { get; set; }
internal IdentityOptions Options { get; set; }
public async Task<IdentityResult> ChangePasswordAsync(TenantUser user, string newPassword)
{
ThrowIfDisposed();
var passwordStore = GetPasswordStore();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
var result = await UpdatePasswordHash(passwordStore, user, newPassword);
if (!result.Succeeded)
{
return result;
}
return await UpdateUserAsync(user);
// Logger.LogWarning(2, "Change password failed for user {userId}.", await GeTenantUserIdAsync(user));
// return IdentityResult.Failed(ErrorDescriber.PasswordMismatch());
}
private static string NewSecurityStamp()
{
return Guid.NewGuid().ToString();
}
private IUserSecurityStampStore<TenantUser> GetSecurityStore()
{
var cast = Store as IUserSecurityStampStore<TenantUser>;
if (cast == null)
{
throw new NotSupportedException("Resources.StoreNotIUserSecurityStampStore");
}
return cast;
}
// Update the security stamp if the store supports it
internal async Task UpdateSecurityStampInternal(TenantUser user)
{
if (SupportsUserSecurityStamp)
{
await GetSecurityStore().SetSecurityStampAsync(user, NewSecurityStamp(), CancellationToken);
}
}
internal async Task<IdentityResult> UpdatePasswordHash(IUserPasswordStore<TenantUser> passwordStore,
TenantUser user, string newPassword, bool validatePassword = true)
{
if (validatePassword)
{
var validate = await ValidatePasswordInternal(user, newPassword);
if (!validate.Succeeded)
{
return validate;
}
}
var hash = newPassword != null ? PasswordHasher.HashPassword(user, newPassword) : null;
await passwordStore.SetPasswordHashAsync(user, hash, CancellationToken);
await UpdateSecurityStampInternal(user);
return IdentityResult.Success;
}
private async Task<IdentityResult> ValidateUserInternal(TenantUser user)
{
var errors = new List<IdentityError>();
foreach (var v in UserValidators)
{
var result = await v.ValidateAsync(this, user);
if (!result.Succeeded)
{
errors.AddRange(result.Errors);
}
}
if (errors.Count > 0)
{
// Logger.LogWarning(13, "User {userId} validation failed: {errors}.", await GeTenantUserIdAsync(user), string.Join(";", errors.Select(e => e.Code)));
return IdentityResult.Failed(errors.ToArray());
}
return IdentityResult.Success;
}
private async Task<IdentityResult> ValidatePasswordInternal(TenantUser user, string password)
{
var errors = new List<IdentityError>();
foreach (var v in PasswordValidators)
{
var result = await v.ValidateAsync(this, user, password);
if (!result.Succeeded)
{
errors.AddRange(result.Errors);
}
}
if (errors.Count > 0)
{
// Logger.LogWarning(14, "User {userId} password validation failed: {errors}.", await GeTenantUserIdAsync(user), string.Join(";", errors.Select(e => e.Code)));
return IdentityResult.Failed(errors.ToArray());
}
return IdentityResult.Success;
}
private async Task<IdentityResult> UpdateUserAsync(TenantUser user)
{
var result = await ValidateUserInternal(user);
if (!result.Succeeded)
{
return result;
}
await UpdateNormalizedUserNameAsync(user);
await UpdateNormalizedEmailAsync(user);
return await Store.UpdateAsync(user, CancellationToken);
}
private IUserPasswordStore<TenantUser> GetPasswordStore()
{
var cast = Store as IUserPasswordStore<TenantUser>;
if (cast == null)
{
throw new NotSupportedException("Resources.StoreNotIUserPasswordStore"); //Resources are not awailable
}
return cast;
}
/// <summary>
/// Releases the unmanaged resources used by the role manager and optionally releases the managed resources.
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
Store.Dispose();
_disposed = true;
}
}
protected void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
}

Related

How to make a common class for common code in a controller

I have two controllers both are derivated from a base controller. The code inside them is exactly the same. The only difference is in constructors. Below is my code:
[RoutePrefix("api/v2")]
public class CategoryController : BaseController
{
private IGetTroubleTicketService getTroubleTicketService;
private ICategoryService categoryService;
/// <summary>
/// Constructor for initialization
/// </summary>
public CategoryController()
{
getTroubleTicketService = MethodFactory.Create<IGetTroubleTicketService>();
getTroubleTicketService.SetProvider(new ServiceProvider(Global.Container));
categoryService = MethodFactory.Create<ICategoryService>();
categoryService.SetProvider(new ServiceProvider(Global.Container));
}
/// <summary>
/// Retrieve all Categories
/// </summary>
/// <returns>Categories(Id, Label)</returns>
[HttpGet]
[Route("categoryRef")]
public HttpResponseMessage Categories()
{
try
{
// Validate User Id and Application Id
var user = ValidateUserAndApplication(getTroubleTicketService);
var userLanaguage = Convert.ToInt32(user.Language, CultureInfo.InvariantCulture);
var categories = categoryService.CategoriesData(userLanaguage);
LoggingRequest("categoryRef",null);
response = Request.CreateResponse(HttpStatusCode.OK, categories);
}
catch (Exception exception)
{
//CheckError
CheckError(exception);
}
return response;
}
}
The second one is
[RoutePrefix("api/v2")]
public class ProblemCategoryController : BaseController
{
private IGetTroubleTicketService getTroubleTicketService;
private ICategoryService categoryService;
/// <summary>
/// Constructor for initialization
/// </summary>
public ProblemCategoryController()
{
getTroubleTicketService = MethodFactory.Create<IGetTroubleTicketService>();
getTroubleTicketService.SetProvider(new ServiceProvider(Global.Container));
categoryService = MethodFactory.Create<ICategoryService>();
categoryService.SetProvider(new ServiceProvider(Global.Container));
}
/// <summary>
/// Retrieve all Natures of problem
/// </summary>
/// <returns>Categories(Id, Label)</returns>
[HttpGet]
[Route("problemCategoryRef")]
public HttpResponseMessage ProblemCategories()
{
try
{
// Validate User Id and Application Id
var user = ValidateUserAndApplication(getTroubleTicketService);
var userLanaguage = Convert.ToInt32(user.Language, CultureInfo.InvariantCulture);
var categories = categoryService.CategoriesData(userLanaguage);
LoggingRequest("problemCategoryRef", null);
response = Request.CreateResponse(HttpStatusCode.OK, categories);
}
catch (Exception exception)
{
//CheckError
CheckError(exception);
}
return response;
}
Now as you can see the internal code is exactly the same which I want to avoid creating a Helper class. How can I make this common class for it so as to remove code duplicacy? It's possible without rewrite all the context code to get User and Id app?
I tried this
public class NatureOfProblemHelper : BaseController
{
private IGetTroubleTicketService getTroubleTicketService;
private ICategoryService categoryService;
private string resourceName;
/// <summary>
/// Initializes a new instance of the <see cref="NatureOfProblemHelper"/> class.
/// Constructor for initialization.
/// <param name="resource">Resource requested by user.</param>
/// </summary>
public NatureOfProblemHelper(string resource)
{
getTroubleTicketService = MethodFactory.Create<IGetTroubleTicketService>();
getTroubleTicketService.SetProvider(new ServiceProvider(Global.Container));
categoryService = MethodFactory.Create<ICategoryService>();
categoryService.SetProvider(new ServiceProvider(Global.Container));
resourceName = resource;
}
/// <summary>
/// Retrieve all Natures of problem.
/// </summary>
/// <returns>Categories(Id, Label).</returns>
public HttpResponseMessage GetNaturesOfProblem()
{
// Validate User Id and Application Id
var user = ValidateUserAndApplication(getTroubleTicketService);
var userLanaguage = Convert.ToInt32(user.Language, CultureInfo.InvariantCulture);
var categories = categoryService.CategoriesData(userLanaguage);
LoggingRequest(resourceName, null);
return Request.CreateResponse(HttpStatusCode.OK, categories);
}
And then into each controller
[HttpGet]
[Route("problemCategoryRef")]
public HttpResponseMessage ProblemCategories()
{
try
{
response = natureOfProblem.NaturesOfProblem();
}
catch (Exception exception)
{
//CheckError
CheckError(exception);
}
return response;
}
This build, but I can't get the context that comes from this variable
// Validate User Id and Application Id
var user = ValidateUserAndApplication(getTroubleTicketService);
Why if I put the same lines of code directly in my controller works but if I put in my Helper it doesn't work??

Requiring all parameters or return 404

I am trying to require the user to input all parameters into the URL like this:
http://127.0.0.1:5000/api/movies/1?foo=a&bar=c
The browser displays;
1 a c
I would like to ensure that all parameters are included in the URL, and the other combinations of parameters would result in 404. How do I modify the code to do this?
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using MoviesAPI.Services;
namespace MoviesAPI.Controllers
{
public interface IActionConstraint : IActionConstraintMetadata
{
/// <summary>
/// The constraint order.
/// </summary>
/// <remarks>
/// Constraints are grouped into stages by the value of <see cref="Order"/>. See remarks on
/// <see cref="IActionConstraint"/>.
/// </remarks>
/// <summary>
/// Determines whether an action is a valid candidate for selection.
/// </summary>
/// <param name="context">The <see cref="ActionConstraintContext"/>.</param>
/// <returns>True if the action is valid for selection, otherwise false.</returns>
bool Accept(ActionConstraintContext context);
}
public class RequiredFromQueryActionConstraint : IActionConstraint
{
private readonly string _parameter;
public RequiredFromQueryActionConstraint(string parameter)
{
_parameter = parameter;
}
public bool Accept(ActionConstraintContext context)
{
if (!context.RouteContext.HttpContext.Request.Query.ContainsKey(_parameter))
{
return false;
}
return true;
}
}
public class RequiredFromQueryAttribute : FromQueryAttribute, IParameterModelConvention
{
public void Apply(ParameterModel parameter)
{
if (parameter.Action.Selectors != null && parameter.Action.Selectors.Any())
{
parameter.Action.Selectors.Last().ActionConstraints.Add(new RequiredFromQueryActionConstraint(parameter.BindingInfo?.BinderModelName ?? parameter.ParameterName));
}
}
}
[Route("api/[controller]")]
public class MoviesController : Controller
{
private MoviesDbContext _context;
public MoviesController(MoviesDbContext context)
{
_context = context;
}
public IActionResult GetMovies()
{
return Ok(_context.Movies);
}
[HttpGet("{id}")]
public string Get(int id, [RequiredFromQuery]string foo, [RequiredFromQuery]string bar)
{
return id + " " + foo + " " + bar;
}
}
}
IActionConstraint Interface is included in Microsoft.AspNetCore.Mvc.ActionConstraints.
Remove your interface code and add the Order property for the RequiredFromQueryActionConstraint
public class RequiredFromQueryActionConstraint : IActionConstraint
{
private readonly string _parameter;
public RequiredFromQueryActionConstraint(string parameter)
{
_parameter = parameter;
}
public int Order => 999;
public bool Accept(ActionConstraintContext context)
{
if (!context.RouteContext.HttpContext.Request.Query.ContainsKey(_parameter))
{
return false;
}
return true;
}
}
public class RequiredFromQueryAttribute : FromQueryAttribute, IParameterModelConvention
{
public void Apply(ParameterModel parameter)
{
if (parameter.Action.Selectors != null && parameter.Action.Selectors.Any())
{
parameter.Action.Selectors.Last().ActionConstraints.Add(new RequiredFromQueryActionConstraint(parameter.BindingInfo?.BinderModelName ?? parameter.ParameterName));
}
}
}
Refer to https://www.strathweb.com/2016/09/required-query-string-parameters-in-asp-net-core-mvc/

How to configure Ninject in call scope binding within Azure Web Job?

I am facing a problem when try to write a web job scheduler. I am using Ninject scope binding using EF Repository pattern. But Only InSingletonScope() work as expected. How to configure it in RequestScope Or Call Scope ?
//Register Context
Kernel.Bind<MyDbContext>().ToSelf().InSingletonScope();
Kernel.Bind<IUnitOfWork<MyDbContext>>().To<UnitOfWork<MyDbContext>>().InSingletonScope();
Problem Solved From One of My Previous Post
I am posting Step By Step Solution
(1.) NinjectJobActivator
public class NinjectJobActivator : IJobActivator
{
#region Variable Declaration
private readonly IResolutionRoot _resolutionRoot;
#endregion
#region CONSTRUCTOR
/// <summary>
///
/// </summary>
/// <param name="kernel"></param>
// public NinjectJobActivator(IKernel kernel)
public NinjectJobActivator(IResolutionRoot resolutionRoot)
{
_resolutionRoot = resolutionRoot;
}
#endregion
#region CreateInstance
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public T CreateInstance<T>()
{
return _resolutionRoot.Get<T>(new CallScopedParameter());
}
#endregion
}
(2) NinjectBindings
using Ninject.Extensions.Conventions;
using Ninject.Extensions.NamedScope;
public class NinjectBindings : NinjectModule
{
public override void Load()
{
//Register Context
Kernel.Bind<MyDbContext>().ToSelf()
.When(x => x.Parameters.OfType<CallScopedParameter>().Any())
.InCallScope(); // For Scheduler
Kernel.Bind<IUnitOfWork<MyDbContext>>().To<UnitOfWork<MyDbContext>>();
//Register Repository
Kernel.Bind(x => x
.FromAssemblyContaining<MyDbContext>()
.SelectAllClasses()
.InheritedFrom(typeof(IRepository<>))
.BindDefaultInterface());
}
}
(3) Program.cs
static void Main()
{
using (IKernel kernel = new StandardKernel(new NinjectBindings()))
{
var config = new JobHostConfiguration()
{
JobActivator = new NinjectJobActivator(kernel)
};
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
// Timer Trigger
config.UseTimers();
var host = new JobHost(config);
//// The following code ensures that the WebJob will be running continuously
host.RunAndBlock();
}
}
(4) CallScopedParameter
public sealed class CallScopedParameter : IParameter
{
/// <summary>
///
/// </summary>
/// <param name="other"></param>
/// <returns></returns>
public bool Equals(IParameter other)
{
if (other == null)
{
return false;
}
return other is CallScopedParameter;
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
/// <param name="target"></param>
/// <returns></returns>
public object GetValue(IContext context, ITarget target)
{
throw new NotSupportedException("this parameter does not provide a value");
}
/// <summary>
///
/// </summary>
public string Name
{
get { return typeof(CallScopedParameter).Name; }
}
/// <summary>
/// this is very important
/// </summary>
public bool ShouldInherit
{
get { return true; }
}
}
(5) Azure Web Job Function
public void DoSomething([TimerTrigger("*/30 * * * * *")] TimerInfo timer, TextWriter log)
{
try
{
var tempdetails = _sampleRepository.SearchFor(x=> DateTime.UtcNow > x.DateTo);
foreach (var detail in tempdetails)
{
if (detail.ID == 2)
{
detail.ID = 5;
}
_sampleRepository.Update(detail);
}
_unitOfWork.Commit();
}
catch (Exception ex)
{
log.WriteLine(ex.Message);
}
}

How can I redirect from my controller using AuthorizeAttributes?

I have made an AuthorizeAttributeBase to extend AuthorizeAttribute.
It looks like this:
public abstract class MyAuthorizeAttribute : AuthorizeAttribute
{
//Holds the roles allowed to perform the action.
public IEnumerable<string> roles { get; set; }
/// <summary>
/// Authorizes if the current user may perform the action
/// </summary>
/// <param name="httpContext">Unused - included for override purposes.</param>
/// <returns>true if authorized.</returns>
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//Return true if user is in the action allowed roles.
if (IsUserInRole)
{
return true;
}
else
{
HttpContext.Current.Response.StatusCode = 401;
return false;
}
}
/// <summary>
/// Checks if the user is member of a role that is allowed by the authorization
/// </summary>
public bool IsUserInRole
{
get
{
if (roles != null)
{
//Check if any of the roles in the session is in the list of roles of the authorization
return (MySessionGetter.GetSession().Roles.Intersect<string>(roles).Any());
}
//If none of the roles match return false.
return false;
}
}
/// <summary>
/// Sets the allowed roles of the authorization
/// </summary>
/// <param name="userRoles">Allowed roles</param>
public void AlowedRoles(IEnumerable<string> userRoles)
{
roles = userRoles;
}
I keep the allowed rolenames like this:
/// <summary>
/// Holds the role names.
/// </summary>
public static class UserRoles
{
public static string Administrators = "Administrators";
public static string Teachers= "Teachers";
}
And use my base like this:
/// <summary>
/// Authorization for the access to the SomeAction
/// </summary>
public class AuthorizeAccessToSomeActionAttribute : MyAuthorizeAttribute
{
public AuthorizeAccessToSomeActionAttribute()
{
AlowedRoles(new List<string> { UserRoles.Adminstrators,
UserRoles.Teachers });
}
}
And last but not least the controller:
/// <summary>
/// The main Index view of application
/// </summary>
/// <returns>Application Index views</returns>
[AuthorizeAccessToSomeAction]
public ActionResult Index()
{
return View("Index");
}
Now what I want to do is make the index switch return value on base of the AuthorizeAttributes.
Lets say Teachers to the TeachersIndex() and Administrators to the AdministratorsIndex().
I tried adding this to the base:
//Checks if the current user is authorized.
public bool IsAuthorized()
{
return AuthorizeCore(new HttpContextWrapper());
}
But I end up having to create new AutorizeAttributes every time.
Making it static seemed to give me even more problems.
Is there a correct way of going about this?
Solved it. :)
The OnAuthorization override got me a new lead.
Found this question.
I put the redirects in a Dictionary<string, RedirectToRouteResult> because I like the idea of keeping all role strings in one place instead of filling up my controllers with magic strings.
public static Dictionary<string, RedirectToRouteResult> HomeRedirect
{
get
{
return new Dictionary<string, RedirectToRouteResult> {
{"Administrators", new RedirectToRouteResult(
new RouteValueDictionary { { "action", "AdministratorIndex" }, { "controller", "MyController" }})},
{"Teacher", new RedirectToRouteResult(
new RouteValueDictionary { { "action", "TeacherIndex" }, { "controller", "MyController" }})}
};
And the override HandleUnauthorizedRequest looks like this now:
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
filterContext.Result = UserRoles.HomeRedirect
.SingleOrDefault(m => m.Key == MySessionGetter.GetSession().Roles.First()).Value;
}
Take a look at RedirectToRouteResult and RedirectResult.
Here would be a good start:
// Redirects users of given role to given action
public class AuthorizeAccessToSomeActionAttribute : MyAuthorizeAttribute
{
public string Role { get; set; }
public string RedirectToAction { get; set; }
public AuthorizeAccessToSomeActionAttribute(string role, string action)
{
Role = role;
RedirectToAction = action;
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
// Test if current user is in the role
if (filterContext.HttpContext.User.IsInRole(Role))
{
// Get current routevalues
var rvals = filterContext.RouteData.Values;
// Change action
rvals["action"] = RedirectToAction;
filterContext.Result = new RedirectToRouteResult("Default",rvals);
}
}
}
Usage:
// Redirect role to given action
[AuthorizeAccessToSomeActionAttribute("Teacher", "TeacherIndex" )]
[AuthorizeAccessToSomeActionAttribute("Admin", "AdminIndex" )]
public ActionResult Index()
...
public ActionResult TeacherIndex()
...
public ActionResult AdminIndex()

WCF services, loading data from database

I have some problem with WCF services in asp.net mvc application.
Help me please!
When I run my project some data for some entities are loading from database, but some data are not loading(Internal server error).
Code and description of exceptions:
EntityTypeController:
public HttpResponseMessage GetAll()
{
//for debug
var t = EntityTypeService.GetAll();
//some exception here!
/*
The request channel timed out while waiting for a reply after 00:00:59.9979999.
Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding.
The time allotted to this operation may have been a portion of a longer timeout.
*/
//SendTimeout is 00:30:00 for all services.
or
/*The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.*/
or
/*An error occurred while receiving the HTTP response to http://localhost:18822/Services/Department.svc.
This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an
HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details.*/
return CreateResponse<IEnumerable<EntityType>>(EntityTypeService.GetAll);
}
EntityTypeService:
public class EntityTypeService : BaseService<Base.Entities.EntityType>, IEntityTypeService
{
public IQueryable<Base.Entities.EntityType> GetAll()
{
var t = Repository.Get();
return t;
}
}
Repository:
public class Repository<TEntity>: IRepository<TEntity> where TEntity: BaseEntity
{
[Inject]
public IDataContext Context { get; set; }
[Inject]
public IDatabase DataSource { get; set; }
/// <summary>
/// Get entities from repository
/// </summary>
/// <param name="filter">Filter</param>
/// <param name="orderBy">Order by property</param>
/// <param name="includeProperties"></param>
/// <returns></returns>
public virtual IQueryable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
var query = Context.Set<TEntity>().AsQueryable();
// Apply filter
filter.Do((s) => {
query = query.Where(filter);
});
// Apply includes
foreach (var includeProperty in includeProperties.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
// Apply order by if need
var result = orderBy
.With(x => x(query))
.Return(x => x, query);
return result;
}
/// <summary>
/// Find entity by key
/// </summary>
/// <param name="id">Identificator</param>
/// <returns>Entity</returns>
public virtual TEntity GetById(object id)
{
//throw new NotImplementedException();
return Context.Set<TEntity>().Find(id);
}
/// <summary>
/// Add new entity to repository
/// </summary>
/// <param name="entity">New entity</param>
public virtual void Insert(TEntity entity)
{
AttachIsNotAttached(entity);
Context.Set<TEntity>().Add(entity);
Context.SaveChanges();
}
/// <summary>
/// Updated entity in repositoy
/// </summary>
/// <param name="entity">Entity</param>
public virtual void Update(TEntity entity)
{
AttachIsNotAttached(entity);
Context.Entry(entity).State = EntityState.Modified;
Context.SaveChanges();
}
/// <summary>
/// Remove entity from rpository
/// </summary>
/// <param name="entity">Entity</param>
public virtual void Delete(TEntity entity)
{
AttachIsNotAttached(entity);
Context.Set<TEntity>().Remove(entity);
Context.Entry(entity).State = EntityState.Deleted;
Context.SaveChanges();
}
/// <summary>
/// Return models error
/// </summary>
/// <returns></returns>
public IEnumerable<object> GetValidationModelErrors()
{
return Context.GetValidationErrors();
}
/// <summary>
/// Attach entity
/// </summary>
/// <param name="entity"></param>
protected void AttachIsNotAttached(TEntity entity)
{
if (Context.Entry(entity).State == EntityState.Detached)
{
var attached = Context.Set<TEntity>().Local.Where(x => x.Id == entity.Id).FirstOrDefault();
attached.Do((s) => {
Context.Entry(s).State = EntityState.Detached;
});
Context.Set<TEntity>().Attach(entity);
}
}
}
By default the wcf config has many limitations like the max size of array, and the exception doesnt exactly what happens,maybe in your case it's due to the default wcf config, I advice you to use svcTraceViewer, it will help you a lot to understand what happen exactly with an explicit messages.

Resources