SharePoint - VirtualPathProvider: Register within FeatureReceiver - asp.net

I'm trying to implement an VirtualPathProvider for SharePoint 2010/2013 (Server and Foundation). So far I've implemented subclasses of System.Web.Hosting.VirtualPathProvider, System.Web.Hosting.VirtualFile and System.Web.Hosting.VirtualDirectory.
I wanted to use a feature with FeatureReceiver class to register the new VPP with the HostingEnvironment. But since I have implemented the line
HostingEnvironment.RegisterVirtualPathProvider(new MyVPProvider());
into the FeatureActivated method, VisualStudio's debug deployment fails with:
Error occurred in deployment step 'Activate Features': Operation is not valid due to the current state of the object.
I have no idea what I am doing wrong. Maybe a FeatureReceiver is the wrong place to register the VPP?
I've already searched the web for an tutorial or example but I didn't find any suitable. Any hint on how to develop a VirtualPathProvider for SharePoint is much appreciated! Thanks in advance.
--
Robert Vogel

You need to write an IHttpModule implementation which registers your virtual path provider ones.
Maybe this link helps you: SharePoint 2007 as a WCF host - Step #4, Write a Virtual Path Provider
using System.Web;
public class MyVirtualPathProviderRegisterModule : IHttpModule
{
static bool _Initialized = false;
static object _Lock = new object();
public void Init(HttpApplication app)
{
if (!_Initialized)
lock(_Lock)
if(!_Initialized)
{
HostingEnvironment.RegisterVirtualPathProvider(new MyVirtualPathProvider());
_Initialized = true;
}
}
public void Dispose() {}
}

Related

how to get HttpContext.Current.GetOwinContext() in startup

I very read for this problem but i can not fixed this so i think create a new question in this site.
HttpContext.Current.GetOwinContext();
i want get GetOwinContext values with above code . above code there are in my startup.cs
[assembly: OwinStartupAttribute(typeof(OwinTest.Startup))]
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var c = HttpContext.Current.GetOwinContext();
}
}
and i get this error
//No owin.Environment item was found in the context
but var c = HttpContext.Current.GetOwinContext(); work for me in HomeController fine.!
I just get GetOwinContext in my startup.cs class.
thankfull
You can't do that. The OWIN context does not exist without a request, and the Startup class only runs once for the application, not for each request. Your Startup class should initialize your middleware and your application and the middleware and the application should access the OWIN context when needed.
As mentioned, what you are asking isn't possible. However, depending on your requirements, the following is possible and gives you access within the context of creating object instances. This is something I needed in order to check for whether an instance was already added else where (I have multiple startup classes in different projects).
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
// Ensure we have our "main" access setup
app.CreatePerOwinContext<DataAccessor>(
(options, owinContext) =>
{
// Check that an instance hasn't already been added to
// the OwinContext in another plugin
return owinContext.Get<DataAccessor>() ?? DataAccessor.CreateInstance(options, owinContext);
}
);
}
Within the CreatePerOwinContext we have access to the OwinContext, so we can access it at the point of creating a new type. This might not help everyone as it's a little more specific to a person's needs, but is useful to know.

Repository pattern with mvc without entity framework

Is repository pattern with unit of work best fit for entity framework application?
I am creating a new asp.net mvc application and i want to use stored procedure (microsoft enterprise library) instead of Entity framework(or any other ORM).
So how can i use repository pattern with mvc application?
I have explored many tutorials but not getting expected result. Please suggest me better approach for n tier application.
You have to understand that "repository pattern" is just an idea to organize your code. I think you can still use it without any problem.
I just want to provide you an example of implementation using sql stored procedure: suppose you have to manage the classic table "Contacts".
You can create your UnitOfWork contract:
public interface IContactsRepository {
void AddContact(Contact c);
void RemoveContact(Contact c);
void UpdateContact(Contact c);
void Search(string keyword);
}
After, you can create your own implementation without using EF:
public sealed class SPContactsRepository : IContactsRepository {
// Is just an exampl.e
public void AddContact(Contact c) {
var sqlCommnad = new SqlCommand(this._connectionString);
sqlCommand.CommandText = "dbo.AddContact";
sqlCommand.CommandType = CommandType.StoredProcedure;
sqlCommand.AddParameter("Name", c.Name);
sqlCommand.Connection.Open();
sqlCommand.ExecuteNonQuery();
}
}
Hope this can help!
So just to continue what Roberto already started, your controller in the MVC app will look like this:
public class ContactsController : Controller
{
private readonly IContactsRepository _contactsRepo;
public ContactsController(IContactsRepository repo)
{
_contactsRepo = repo;
}
}
These pattern uses dependency injection(DI). There are several options for DI container. You can use Unity which is a Microsoft package that you can install via nuget package manager to your MVC web project. The install will create a UnityConfig.cs file in your App_Start folder. You can register the dependency as:
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IContactsRepository, SPContactsRepository>();
}
And in your Global.asax.cs file inside Application_Start(), you initialize the container:
UnityConfig.RegisterComponents();
If you use EF, the DbContext is already your Unit of Work and the DbSet as your repository. Having said that, you should not create a repository that will add another layer of data abstraction. Instead, you can create, domain services.

Can I use my Ninject .NET project within Orchard CMS?

I am creating a website using Orchard CMS and I have an external .NET project written with Ninject for dependency injection which I would like to use together with a module within Orchard CMS. I know that Orchard uses Autofac for dependency injection and this is causing me problems since I never worked with DI before.
I have created an Autofac module, UserModule, which registers the a source, UserRegistrationSource, like this:
UserModule.cs
public class UserModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterSource(new UserRegistrationSource());
}
}
UserRegistrationSource.cs
public class UserRegistrationSource : IRegistrationSource
{
public bool IsAdapterForIndividualComponents
{
get { return false; }
}
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var serviceWithType = service as IServiceWithType;
if (serviceWithType == null)
yield break;
var serviceType = serviceWithType.ServiceType;
if (!serviceType.IsInterface || !typeof(IUserServices).IsAssignableFrom(serviceType) || serviceType != typeof(IUserServices))
yield break;
var registrationBuilder = // something...
yield return registrationBuilder.CreateRegistration();
}
}
UserServices.cs
public interface IUserServices : IDependency
{
void Add(string email, string password);
}
public class UserServices : IUserServices
{
private readonly EFMembershipManager _manager;
public UserServices(EFMembershipManager manager)
{
_manager = manager;
}
public void Add(string email, string password)
{
_manager.createUser(email, password);
}
}
EFMembershipManager.cs constructor
public EFMembershipManager(ServerRepository db,
ServerRepositoryMembershipProvider membershipProvider,
string testUsername,
string serverUsername)
{
...
}
EFMembershipManager is a class from the external project which uses Ninject for DI's and uses ServerRepository and ServerRepositoryMembershipProvider whom also are injected using Ninject.
And now I'm stuck...
Should UserRegistrationSource take the Ninject container (kernel) as a constructor argument and try to find the IUserServices service and then mediate the resolves to the Ninject kernel and return an empty Enumerable so that Autofac doesn't try to resolve anything related to IUserServices or is this the wrong approach?
Autofac supports registration sources (and more on registration sources here). A registration source is a service that the container will consult when trying to resolve a type. The source can respond, either with a means to build the type, or an empty list which indicates that the source is not able to provide the requested type.
In your case, a registration source could be implemented that will try to resolve the requested type from your Ninject container.
I'm not too familiar with Orchard but I'm guessing that it uses configuration files to configure Autofac. My suggestion is that you create a simple Autofac module that registers your registration source implementation, and that you configure Orchard to load the module from config.

Asp.Net 3.5 Routing to Webservice?

I was looking for a way to route http://www.example.com/WebService.asmx to http://www.example.com/service/ using only the ASP.NET 3.5 Routing framework without needing to configure the IIS server.
Until now I have done what most tutorials told me, added a reference to the routing assembly, configured stuff in the web.config, added this to the Global.asax:
protected void Application_Start(object sender, EventArgs e)
{
RouteCollection routes = RouteTable.Routes;
routes.Add(
"WebService",
new Route("service/{*Action}", new WebServiceRouteHandler())
);
}
...created this class:
public class WebServiceRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
// What now?
}
}
...and the problem is right there, I don't know what to do. The tutorials and guides I've read use routing for pages, not webservices. Is this even possible?
Ps: The route handler is working, I can visit /service/ and it throws the NotImplementedException I left in the GetHttpHandler method.
Just thought I would round off this question with a bit more of a detailed solution based on the answer given by Markives that worked for me.
Firstly here is the route handler class which takes the virtual directory to your WebService as its constructor param.
public class WebServiceRouteHandler : IRouteHandler
{
private string _VirtualPath;
public WebServiceRouteHandler(string virtualPath)
{
_VirtualPath = virtualPath;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new WebServiceHandlerFactory().GetHandler(HttpContext.Current,
"*",
_VirtualPath,
HttpContext.Current.Server.MapPath(_VirtualPath));
}
}
and the actual usage of this class within the routey bit of Global.asax
routes.Add("SOAP",
new Route("soap", new WebServiceRouteHandler("~/Services/SoapQuery.asmx")));
This is for anyone else who wants to do the above. I found it incredibly difficult to find the information.
In the GetHttpHandler(byVal requestContext as RequestContext) as IHttpHandler Implements IRouteHandler.GetHttpHandler method (my version of the above)
This is for Webforms 3.5 by the way (mine's in VB).
You cant use the usual BuildManager.CreateInstanceFromVirtualPath() method to invoke your web servce that's only for things that implement iHttpHandler which .asmx doesn't. Instead you need to:
Return New WebServiceHandlerFactory().GetHandler(
HttpContext.Current, "*", "/VirtualPathTo/myWebService.asmx",
HttpContext.Current.Server.MapPath("/VirtualPathTo/MyWebService.aspx"))
The MSDN documentation says that the 3rd parameter should be the RawURL, passing HttpContext.Current.Request.RawURL doesn't work, but passing the virtual path to the .asmx file instead works great.
I use this functionality so that my webservice can be called by any Website configured in anyway (even a virtual directory) that points (in IIS) to my application can call the application web service using something like "http://url/virtualdirectory/anythingelse/WebService" and the routing will always route this to my .asmx file.
You need to return an object that implements IHttpHandler, that takes care of your request.
You can check out this article on how to implement a webservice using that interface: http://mikehadlow.blogspot.com/2007/03/writing-raw-web-service-using.html
But this is probably closer to what you want http://forums.asp.net/p/1013552/1357951.aspx (There is a link, but it requires registration, so I didnt test)

Programmatically register HttpModules at runtime

I'm writing an app where 3rd party vendors can write plugin DLLs and drop them into the web app's bin directory. I want the ability for these plugins to be able to register their own HttpModules if necessary.
Is there anyway that I can add or remove HttpModules from and to the pipeline at runtime without having a corresponding entry in the Web.Config, or do I have to programmatically edit the Web.Config when adding / removing modules? I know that either way is going to cause an AppDomain restart but I'd rather be able to do it in code than having to fudge the web.config to achieve the same effect.
It has to be done at just the right
time in the HttpApplication life cycle
which is when the HttpApplication
object initializes (multiple times,
once for each instance of
HttpApplication). The only method
where this works correct is
HttpApplication Init().
To hook up a module via code you can
run code like the following instead of
the HttpModule definition in
web.config:
public class Global : System.Web.HttpApplication
{
// some modules use explicit interface implementation
// by declaring this static member as the IHttpModule interface
// we work around that
public static IHttpModule Module = new xrnsToashxMappingModule();
public override void Init()
{
base.Init();
Module.Init(this);
}
}
All you do is override the HttpApplication's Init() method and
then access the static instance's Init
method. Init() of the module hooks up
the event and off you go.
Via Rick Strahl's blog
Realize this is an old question, but asp.net 4 provides some new capabilities that can help here.
Specifically, ASP.NET 4 provides a PreApplicationStartMethod capability that can be used to add HttpModules programmatically.
I just did a blog post on that at http://www.nikhilk.net/Config-Free-HttpModule-Registration.aspx.
The basic idea is you create a derived HttpApplication that provides ability to add HttpModules dynamically at startup time, and it then initializes them into the pipeline whenever each HttpApplication instance is created within the app-domain.
The dll Microsoft.Web.Infrastructure.dll has a method for this inside the class DynamicModuleUtility.
The dll is shipped with WebPages 1.0
public static class PreApplicationStartCode
{
private static bool _startWasCalled;
public static void Start()
{
if (_startWasCalled) return;
_startWasCalled = true;
DynamicModuleUtility.RegisterModule(typeof(EventTriggeringHttpModule));
}
}
This worked for me for dynamic registration.
RegisterModule(typeof(RequestLoggerModule));
public class RequestLoggerModule : IHttpModule
{ ... }
https://learn.microsoft.com/en-us/dotnet/api/system.web.httpapplication.registermodule?view=netframework-4.7.2
In new versions of ASP MVC you can use Package Manager to add a reference to WebActivatorX and then do something like this
using WhateverNameSpacesYouNeed;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(YourApp.SomeNameSpace.YourClass), "Initialize")]
namespace YourApp.SomeNameSpace
{
public static void Initialize()
{
DynamicModuleUtility.RegisterModule( ... the type that implements IHttpModule ... );
}
}

Resources