MVC 3 sub Site? - asp.net-mvc-3

I have a very basic site that works fine on its own but when I create a duplicate of the site and attempt to add it to a sub domain (then convert it to a application) I get a error when I attempt to any controller which has the below settings at the top:
public class AccountController : Controller
{
// This constructor is used by the MVC framework to instantiate the controller using
// the default forms authentication and membership providers.
private CustomMembershipDB datacontext;
public AccountController()
: this(null, null)
{
datacontext = new CustomMembershipDB();
}
// This constructor is not used by the MVC framework but is instead provided for ease
// of unit testing this type. See the comments at the end of this file for more
// information.
public AccountController(IFormsAuthentication formsAuth, IMembershipService service)
{
FormsAuth = formsAuth ?? new FormsAuthenticationService();
MembershipService = service ?? new AccountMembershipService();
}
public IFormsAuthentication FormsAuth
{
get;
private set;
}
public IMembershipService MembershipService
{
get;
private set;
}
Error I get:
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.
Parser Error Message: The entry 'EFMembershipProvider' has already been added.
IIS seems to be complaining about a duplicate Membership provider being set on the same domain and not sure simply renaming it will solve this one? Any Idea appreciated as I'm a newbie and this is above me!

I suppose that your "subsite" is a virtual directory of the first one. Root's Web.config settings are inherited to virtual directories.
That means that by default your subsite gets all providers declared in your top site.
To prevent this behavior you can use this directive inheritInChildApplications=false on your main Web.config or simply avoid to (re)declare the EFMembershipProvider in your subsite.

Related

Web Api 2 with OWIN OAuth Bearer tokens

I'm in the process of building a web api in visual studio 2013 and want to authenticate using OWIN middleware and bearer tokens. However I already have a database and don't want to use Microsoft's new Identity framework as the majority of tables and columns that it auto generates I simply don't need.
Can anyone point me in the right direction of how to apply this type of authentication without having to use the Microsoft Identity framework?
My suggestion would be to use the framework but extend it to use your objects and infrastructure. I am currently in the middle of doing this and landed on this question. Here's how I've tackled it so far:
Step 1: Your own CustomUserObject
Write/Use your own "ApplicationUser" object. In the template project, you want to modify the "IdentityModels" file. It has ApplicationUser object defined in there. Assuming you already have all the properties from your existing app, you will need to add GenerateUserIdentityAsync() method but change the type of the parameter to UserManager manager). After the change, your method signature looks like this:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<CustomUserObject> manager)
Step 2: Define your own IUserStore<> implementation
Add a new class CustomUserStore that implements IUserStore, like so:
public class CustomUserStore : IUserStore<CustomUserObject>
{
private readonly IUserManagerService _userManagerService;
public CustomUserStore(IUserManagerService userManagerService)
{
_userManagerService = userManagerService
}
//implementation code for all of the IUserStore methods here using
//userManagerService or your existing services/classes
}
I am using Unity to inject IUserManagementService's implementation above.
I have made use of the comprehensive UserManager class that comes with the Microsoft Identity framework but extended the framework to use my API for authentication and authorization. You could write your own UserManager but I found that it is pretty tedious and there is no reason why UserManager could work for most cases of Securing an app.
Step 3: Changes in the IdentityConfig.cs file
Change the class definition to make ApplicationUserManager class inherit from UserManager
You'll need to do the samething in the constructor of this class as well; i.e. have IUserStore. Modify the Create static method's first line to make use of the new store and a wrapper class that provides as a means to be a "DbContext" like so:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new ApplicationUserStore(context.Get<UserManagementServiceWrapper>()));
//modify the relevant lines after this to suit your needs
...
}
My UserManagementServiceWrapper looks like this (please note that I'm not too happy that it inherits from a concrete UserManagementService class that provides the methods to connect to the service that provides user data, I'm still building this out):
public class UserManagementServiceWrapper : UserManagementService, IDisposable
{
public void Dispose()
{
throw new NotImplementedException();
}
}
Step 4: Change the ApplicationDbContext class to return a UserManagementServiceWrapper instance
public class ApplicationDbContext : UserManagementServiceWrapper
{
public static UserManagementServiceWrapper Create()
{
return new UserManagementServiceWrapper();
}
}
And that is pretty much it. You still have to write the implementation for CustomUserStore object but everything should work.
Please note this is not boilerplate code and no where near "code review ready", as I said, I'm still digging deeper into this and building it out to use custom stores, data access objects, services etc. I thought you'll get a good start with some of the things that took me a couple of hours to figure out. I will blog about this when I have a good solution.
Hope this helps.
I prob. dont understand the question entirely but it looks like you are trying to do without the whole owin pipeline?
If not then..
You need to implement few interfaces related to users and roles described as below.
http://www.asp.net/identity/overview/extensibility/overview-of-custom-storage-providers-for-aspnet-identity
Have a look at the following post from Scott Allen
http://odetocode.com/blogs/scott/archive/2013/11/25/asp-net-core-identity.aspx
This way you can use your own tables, DAL and services to create UserManager and RoleManager objects.
Edit: Samples over here should give you some pointers.
Edit2: Custom User Store Example.
IRepository is the object which takes care of CRUD.
public class CustomUserStore : IUserStore<User>,....
{
private readonly IRepository _repository;
public CustomUserStore(IRepository repository)
{
if (repository == null)
throw new ArgumentNullException("repository");
_repository = repository;
}
public Task CreateAsync(User user)
{
if (user == null) throw new ArgumentException("user");
_repository.User.Add(user);
return _repository.CommitAsync();
}
...

ASP.Net Web API Help Page Area returning empty output

I have a preexisting MVC app that I added Web API and Web API Self Documentation using Nuget. While the Web API controllers function fine (return valid responses to HTTP requests) the Help controller is not finding any Web API methods to document.
In the Help controller Index action "Configuration.Services.GetApiExplorer().ApiDescriptions" is returning with 0 results.
What populated ApiDescriptions and are there any config settings I need to set to expose my api to documentations?
The Help Area is a separate area from the rest of my application. Is this causing the piece that finds the Controllers to not find my controllers? Furthermore, I even added a help snipped to the HelpController itself, which still resulted in no API descriptions.
I do also have special routing for my API controllers, so I'm not sure if that's relevant.
After some more searching i found this post which also refers to this post
As mentioned in the first post, Glimpse is the culplit, this workaround solved the issue for me:
<glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd">
<inspectors>
<ignoredTypes>
<add type="Glimpse.AspNet.Inspector.RoutesInspector, Glimpse.AspNet"/>
</ignoredTypes>
</inspectors>
</glimpse>
This is also a known issue and the workaround is described on this Glimpse GitHub Issue.
I have the same problem and i don't use Glimpse and i solve the problem like this:
In the ProjectName\Areas\HelpPage\Controllers\HelpController.cs file comment the constructors because is not called the implicit constructor public HelpController() : this(GlobalConfiguration.Configuration) default is called the constructor with the parameter public HelpController(HttpConfiguration config) and this initialization of the Configuration property is incorect. And you cand solve this problem like this:
Solution 1:
Comment/Remove the constructors.
public class HelpController : Controller
{
private const string ErrorViewName = "Error";
// public HelpController()
// : this(GlobalConfiguration.Configuration)
// {
// }
// public HelpController(HttpConfiguration config)
// {
// Configuration = config;
// }
/// <summary>
/// GlobalConfiguration By default
/// </summary>
protected static HttpConfiguration Configuration
{
get { return GlobalConfiguration.Configuration; }
}
public ActionResult Index()
{
ViewBag.DocumentationProvider = Configuration.Services.GetDocumentationProvider();
return View(Configuration.Services.GetApiExplorer().ApiDescriptions);
}
....
Solution 2:
inject the default constructor by add this attribute [InjectionConstructor].
public class HelpController : Controller
{
private const string ErrorViewName = "Error";
[InjectionConstructor]
public HelpController()
: this(GlobalConfiguration.Configuration)
{
}
public HelpController(HttpConfiguration config)
{
Configuration = config;
}
/// <summary>
/// GlobalConfiguration By default
/// </summary>
protected static HttpConfiguration Configuration { get; private set; }
....
And problem solved.
I was able to solve this by adding GlobalConfiguration.Configure (WebApiConfig.Register); in my Application_Start () method. Because my application uses OWIN I was registering my APIs only in Startup.Configuration (IAppBuilder app).
After installing HelpPages package from NuGet package manager- Navigate to WebApplication1\Areas\HelpPage\App_Start\HelpPageConfig.cs and uncomment the line below
config.SetDocumentationProvider(new XmlDocumentationProvider(
HttpContext.Current.Server.MapPath("~/App_Data/XmlDocument.xml")));
Also add App_Data/XmlDocument.xml to WebApplication > Properties > Build > Check XML Documentation File

N-Tier Service Layer Validation Show Business Logic Error in Presentation Layer

I am converting from the old ways of ASP.NET Web Forms to ASP.NET MVC. I have a project that I am working on that has about 40-50 tables in the database. I have decided to use Entity Framework as my data access layer. I have also decided to put a repository layer and unit of work abstraction over EF so that I am not tied to it and so that I can do unit testing. Finally, I want to make my controllers "thin" so I am looking at implementing a business "service" layer for my business logic.
The thing I am struggling with is how do I propagate Business Logic Errors from my service layer to my Presentation UI layer so that an appropriate error can be shown? Please note that I am trying to look for a solution that is NOT MVC specific as this service/business logic layer will likely be used in other things besides an MVC app (console app's, web services, etc.)
On to some code...
Lets say I have a POCO / data / domain model like so:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
// other properties (navigation, etc)...
}
An Entity Framework fluent configuration/mapping class like so:
public class CategoryMap : EntityTypeConfiguration<Category>
{
public CategoryMap()
{
this.HasKey(c => c.Id);
this.Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // auto increment identity in our DB schema
this.Property(c=> c.Name)
.IsRequired() // defined as NOT NULL in DB schema so we put a constraint here
.HasMaxLength(150); // defined as varchar(150) in DB schema so we put a constraint here
this.Property(c=> c.Description)
.IsRequired(); // defined as NOT NULL in DB schema so we put a constraint here
// fluent config for related entities (navigation properties) would go here...
}
}
A unit of work encapsulating multiple repositories like so:
public class UnitOfWork : IUnitOfWork
{
private readonly MyDbContext context;
private CategoryRepository catRepo;
public UnitOfWork()
{
this.context = new MyDbContext();
}
public ICategoryRepository Categories
{
get { return this.catRepo?? (this.catRepo= new CategoryRepository (this.context)); }
}
}
A service / business logic layer like so:
public class CategoryService : ICategoryService
{
private readonly IUnitOfWork unitOfWork;
public CategoryService(IUnitOfWork uow) // injected by IoC
{
this.unitOfWork = uow;
}
public Category CreateNewCategory(Category category)
{
if (category == null)
{
throw new ArgumentNullException("category cannot be null");
}
// Simple business logic here to make sure another category with this name does not already exist.
int count = this.unitOfWork.Categories.Count(cat => cat.Name == category.Name);
if (count > 0)
{
// *** This is the error I want the user to see in the UI ***
throw new Exception("Sorry - a category with that name already exists!");
}
}
}
And a controller like this:
public ManageCategoriesController : Controller
{
ICategoryService catSvc;
public ManageCategoriesController(ICategoryService svc) // injected by IoC
{
this.catSvc = svc;
}
[HttpPost]
public ActionResult(CategoryCreateModel createModel) // my View Models / Create Models have Data Annotations on them
{
if (ModelState.IsValid)
{
// use of AutoMapper to map from View Model to domain model...
Category cat = Mapper.Map<CategoryCreateModel , Category>(createModel);
this.catSvc.CreateNewCategory(cat); // ***need to get potential errors from Service and display on form.***
return this.RedirectToAction("Index");
}
}
}
First of all, can anybody tell me if I am on the right track with using View Models? I feel like I almost have three View Models (Create, Edit, View/List) per domain model.
Secondly, my EF configuration/mapping class takes care of the database constraints. Some of these constraints (e.g. Max length) are also data annotations in the View Models and can easily be displayed on the UI. But where can I show my custom business logic errors?
First, your overall approach to MVC looks good to me :-)
Second, you most likely want to use DataAnnotation on your view models for model validation. Have a look this blog post for a good intro on using it in ASP.MVC.
In case of custom validation not suitable for data annotation you can do the following in your controller:
try
{
// the following exception could be thown by some nested validation logic
// e.g. while processing a post request
throw new ValidationException("the error description");
}
catch (ValidationException exception)
{
ModelState.AddModelError("", exception.Message);
}
This is a pretty old question, but for future readers I'd like to add something.
If you're actually using a N-Tier pattern, entity validation should be in your Service layer. Not in your MVC Controller.
The right way to do it is to do basic model validations in your model class, using ValidationAttributes, but re-validate your entities in your service layer.
Add a handling of custom exceptions in your controller to catch any validation error raised from the service layer, and display error messages.
If your service layer is just there to call your repositories, you're doing something wrong ;)

Plugin Architecture with ninject – load class and controller instances from plugin assembly to main MVC project

I use this tutorial to create Plugin Architecture in my solution and I also use ninject for the first time:
http://www.codeproject.com/script/Articles/ArticleVersion.aspx?aid=358360&av=526320&msg=4308834#xx4308834xx
Now in MVC application while user is in the process of checkout I get the payment method he selects and need to retrieve the plugin for the selected payment method. I have succeeded in retrieving plugin controller this way, though I have no idea whether it is safe or acceptable practice:
Type type = Type.GetType(paymentMethod.PaymentMethodPluginType);
//get plugin controller
var paymentController = ServiceLocator.Current.GetInstance(type) as BasePaymentController;
//get validations from plugin
var warnings = paymentController.ValidatePaymentForm(form);
//get payment info from plugin
var paymentInfo = paymentController.GetPaymentInfo(form);
//…
I also need to access a plugin class for processing the payment.
I have an interface IPaymentMethod
public partial interface IPaymentMethod
{
void PostProcessPayment (PostProcessPaymentRequest postprocessPaymentRequest);
}
And plugin PaymentProcessor like this
public class PluginPaymentProcessor :IPaymentMethod
{
public void PostProcessPayment (PostProcessPaymentRequest postprocessPaymentRequest)
{
///
}
Now in MVC project I try to access PostProcessPayment method this way
IPaymentMethod pluginpaymentmethod = ServiceLocator.Current.GetInstance<IPaymentMethod>(paymentMethod.PaymentProcessor);
here paymentMethod.PaymentProcessor is “MyApp.Plugins.MyPlugin.PluginPaymentProcessor, MyApp.Plugins.MyPlugin,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”
And want to use pluginpaymentmethod like i do in controller example
pluginpaymentmethod.PostProcessPayment(postProcessPaymentRequest);
but it throws error that resource is not found and pluginpaymentmethod is not loaded. How can I fix it or can you suggest any tutorial with similar implementations? Thank you.
assuming you have a concrete class called MyPlugin which has the IPaymentMethod interface, then your ninject bindings should look a bit like:
private static void RegisterServices(IKernel kernel){
kernel.Bind<IPaymentMethod>().To<MyPlugin>().InRequestScope();
}
check that this is in place in your NinjectWebCommon.cs class under the App_Start folder. A trickier scenario might be that IPaymentMethod has to be registered in the same way that the Ninject IKernel is bound:
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
that would potentially be a trickier issue to work out.

ASP.NET MVC 3: Validating model when information external to the model is required

What's a good way to validate a model when information external to the model is required in order for the validation to take place? For example, consider the following model:
public class Rating {
public string Comment { get; set; }
public int RatingLevel { get; set; }
}
The system administrator can then set the RatingLevels for which a comment is required. These settings are available through a settings service.
So, in order to fully validate the model I need information external to it, in this case the settings service.
I've considered the following so far:
Inject the service into the model. The DefaultModelBinder uses System.Activator to create the object so it doesn't go through the normal dependency resolver and I can't inject the service into the model without creating a new model binder (besides which, that doesn't feel like the correct way to go about it).
Inject the service into an annotation. I'm not yet sure this is possible but will investigate further soon. It still feels clumsy.
Use a custom model binder. Apparently I can implement OnPropertyValidating to do custom property validation. This seems the most preferable so far though I'm not yet sure how to do it.
Which method, above or not, is best suited to this type of validation problem?
Option 1 doesn't fit. The only way it would work would be to pull in the dependency via the service locator anti-pattern.
Option 2 doesn't work. Although I couldn't see how this was possible because of the C# attribute requirements, it is possible. See the following for references:
Resolving IoC Container Services for Validation Attributes in ASP.NET MVC
NInjectDataAnnotationsModelValidatorProvider
Option 3: I didn't know about this earlier, but what appears to be a very powerful way to write validators is to use the ModelValidator class and a corresponding ModelValidatorProvider.
First, you create your custom ModelValidatorProvider:
public class CustomModelValidatorProvider : ModelValidatorProvider
{
public CustomModelValidatorProvider(/* Your dependencies */) {}
public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
{
if (metadata.ModelType == typeof(YourModel))
{
yield return new YourModelValidator(...);
}
}
}
ASP.NET MVC's IDependencyResolver will attempt to resolve the above provider, so as long as it's registered with your IoC container you won't need to do anything else. And then the ModelValidator:
public class EntryRatingViewModelValidatorMvcAdapter : ModelValidator
{
public EntryRatingViewModelValidatorMvcAdapter(
ModelMetadata argMetadata,
ControllerContext argContext)
: base(argMetadata, argContext)
{
_validator = validator;
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
if (/* error condition */)
{
yield return new ModelValidationResult
{
MemberName = "Model.Member",
Message = "Rating is required."
};
}
}
}
As the provider is retrieved through the IDependencyResolver and the provider has full control over the returned ModelValidators I was easily able to inject the dependencies and perform necessary validation.
You could try fluent validation. It supports asp.net mvc and DI so you can inject external services into your validators.
Assuming that you want both client and server-side validation of the model based upon the values returned from the service, I would opt for 2., Inject the service into an annotation.
I give some sample code in my response to this question about adding validators to a model. The only additional step in your case is that you will need to inject your service into your class inheriting from DataAnnotationsModelValidatorProvider.
What about just simply using IValidateableObject and in that method determine if validation is appropriate or not and setting the errors there?
How do I use IValidatableObject?

Resources