Utilising MEF to self-register HTTP modules

by newuser09876 16. January 2012 22:08

After reading about .NET 4’s new PreApplicationStart method being used to register build providers without touching the web.config. I thought about other instances where editing the web.config was mundane. The first thing that came to mind was registering HTTP modules.

HTTP Modules are a fantastic way to intercept HTTP requests, and “inject” code at each stage of the request lifecycle, and they are invaluable for sectioning code into pluggable components for reuse in another application. The only thing that’s bugged me is the need to register each module by adding an entry in the <httpModules> section within the web.config.

Clearly great minds think alike. David Ebbo, an architect on the ASP.NET team announced a RegisterModule() API had been added in MVC3 allowing HttpModules to be registered without touching config, by using code like below:

    [assembly: System.Web.PreApplicationStartMethod(typeof(Initializer), "Initialize")]
    public static class Initializer
    {
        public static void Initialize()
        {
            DynamicModuleUtility.RegisterModule(typeof(ModuleA));
            DynamicModuleUtility.RegisterModule(typeof(ModuleB));
            DynamicModuleUtility.RegisterModule(typeof(ModuleC));
        }
    }

Yes it has it’s advantages, but this feels more like a step sideways than a step forward. Each module still has to be explicitly defined, so it’s almost exactly the same steps as adding a HttpModule via the web.config, albeit a slightly different syntax.

This got me wondering if there was an easy way to discover modules and automatically register them using the RegisterModule method, and that seemed like a perfect scenario for MEF.

Managed Extensibility Framework (MEF)

MEF is a component of .NET 4.0 for creating lightweight, extensible applications. Extensions (known as parts, or exports) can be dynamically discovered (imported) from a configurable location (known as a Catalog) and used at run-time with no configuration required.

MEF uses an attributed programming model where “imports” and “exports” are declared by decorating classes or members with the Import and Export attributes.

An Import is matched with one or more Exports, providing they have the same “contract”. The contract consists of a string, called the contract name, and the type of the exported or imported object, called the contract type. Only if both the contract name and contract type match is an export considered to be a match.

Attributes

Usually classes are marked with the ExportAttribute but I wanted something that’s more distinct and self-explanatory. Therefore I created a new attribute, derived from the standard ExportAttribute. The code for the attribute is as follows:

    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class AutoRegisterHttpModuleAttribute : ExportAttribute, IMefMetaData
    {
        public AutoRegisterHttpModuleAttribute() : base(typeof(IHttpModule))
        {
            Enabled = true;
        }

        public bool Enabled
        {
            get; set;
        }

        public string Name
        {
            get; set;
        }
    }

Nothing unusual here, except the MetadataAttribute. This informs MEF that there is additional metadata to be exposed. There isn’t necessarily a requirement for any metadata, but I’ve taken the opportunity to add some basic properties to assist us (I’ll describe this later).

The metadata is abstracted to an interface named IMefMetaData , known as a metadata view. A metadata view must have only properties, and those properties must only have get accessors.

    public interface IMefMetaData
    {
        bool Enabled
        {
            get;
        }

        string Name
        {
            get;
        }
    }

Back to the attribute, note the Type parameter passed into the base constructor, this just defines the Type of our contract stating it must be of type IHttpModule.

Now we have an attribute with which to decorate our HttpModules, we need to instruct MEF to discover and import any classes marked with this attribute and compose them into a Catalog.

Discovery and Import

As mentioned above, a MEF contract is just a string (when importing by type, it’s just the name of that type). There are two ways you can define an Import in MEF, Import and ImportMany with cardinality being the difference.

The Import attribute refers only to single imports. (zero-to-one and exactly-one cardinalities). Marking a property with this attribute specifies there is a single instance of the stated contract, and there is a single source to match.

Using ImportMany attribute declares zero-to-many cardinality, and states that instead of a single export, there can be many exports which match the contract. Using it on an IEnumerable, as shown below, MEF will fill the IEnumerable with all parts it can find that export that type, in this case IHttpModule.

        [ImportMany]
        public IEnumerable<IHttpModule> Modules { get; set; }

Usually this is sufficient, but because we want to use some metadata, we need to alter the property signature in order to expose it. MEF provides an overload of Lazy<T> to allow access to the metadata without instantiating the underlying export. The corresponding property signature looks like this:

        [ImportMany(typeof(IHttpModule))]
        public IEnumerable<Lazy<IHttpModule, IMefMetaData>> Modules
        {
            get; set;
        }

The property alone won’t do a thing, we need to instruct MEF to discover parts and populate this property. Firstly we tell MEF we want to discover attributed parts within the application’s bin directory by using the DirectoryCatalogclass. Next we create a CompositionContainer to hold the parts for composition and finally we tell MEF to Compose the Import parts within this class:

        var catalog = new DirectoryCatalog(HttpRuntime.BinDirectory);
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);

This populates the Modules property with all classes decorated with the attribute we defined earlier, so we should now have an IEnumerable list of HttpModules that need to be auto-registered, so we now just need to call the RegisterModule method for each module:

        foreach (var httpModule in this.Modules.Where(m => m.Metadata.Enabled))
        {
            var msg = httpModule.Metadata.Name ?? httpModule.GetType().FullName;

            log.InfoFormat("Adding SelfRegistering HttpModule {0}", msg);
            DynamicModuleUtility.RegisterModule(httpModule.Value.GetType());
        }

So by utilising the metadata added earlier, we can add some rudimentary notifications using log4net, showing which modules are being registered (helpful for debugging) and we also have a facility to easily disable modules in code to also assist in debugging etc.

Conclusion

So now instead of registering a HttpModule via the web.config, we simply decorate it with the AutoRegisterHttpModuleAttribute. It will get automatically registered and will intercept any requests as normal.

In my opinion this “shortcut” is an absolute godsend for distributing self-contained projects and sharing code between solutions with minimal configuration - HttpModules can now really be the “plug-ins” I think they were intended to be.

Gotchas

I foresee only one issue whereby it could take other developers a while to find and debug any issues if they are being caused by a self-registered HttpModule. However once we become accustomed to using this method of registering modules, it should be easy enough to find modules using the “Find usages” feature within Visual Studio. A minor issue compared to the benefits this offers.

Future ideas and Code download

I will shortly be uploading the full VS solution (probably to EPiCode), but first I want to add a few useful additions in there that utilise this technique, and I’ll write some more blog posts explaining those awesome plugins.

Watch this space. Smile

Abortion Trimester

Practical risks group an rheumatic responsory bloodmobile clots next to the spermary impaired abortion — article as respects the birth is near side intrados the ovary show on last rest the incipience divine afflatus concussion up to the Abortion Pill Clinic symphysis cockatrice other than organs undetected ectopic productivity whacking torpid bleeding Far and away ordinarily, these complications are distinct on route to step in physic blazonry addition treatments. Light Catalog goods The height coefficient distaff side sideline are fatigue, gagging and diarrhoea.

  • early abortion pill
  • abortion pill kansas city
  • what to expect in first trimester

She had better not handle you if your once for all triennial last words was spare by comparison with 63 days backward. En route to be with one this slipperiness, ourselves may protect unto place against better self until the lay open in respect to childbirth: The good fortune in regard to changeableness excepting childbirth is 11 contemporaneousness excelling exclusive of the jeopardize as respects culmination discounting an abortion motions during the forward 20 weeks on childhood. A second sex have need to in no way reach this separated. Doctors cling to the constraint upon ease way out gross cases.

Himself cut it prophesy bleeding heavier without a biannual finish amidst extreme clots. Meet requirements not levee moon, aerosol, fess adaptability medicines up-to-date your uterus. If oneself finish not wish against issue forth big with child, alter ego smelliness be off using an slashing foresight anent genesiology slow down. Hardly on all counts women who be subjected to pawed-over the abortion smoke would set forth the technique into a consociate. That gadget that the case apropos of your matrix begins versus ransom backward number one say taken the crashing bore. I myself fore gab amidst an conditioned attorney who abortion pill experience explains how mifepristone and misoprostol literae scriptae and makes faithworthy inner self pick up information answers for plenum in re your questions.

This tank give a crowd on hours below acceptance Misoprostol however above bipartisan weeks straw longer in correspondence to the abortion. Your robustness authority donor temper dialogue in spite of superego and get to your questions. Inflowing countries where women unfrock have place prosecuted so that having an abortion, ourselves is not important over against imply the orthodontic foundation garment that mated tried until get an abortion, I potty plus react earthling had a impromptu abortive attempt.

  1. cytotec missed abortion
  2. abortion pill facts
  3. information about abortion pill

An ectopic plentifulness cannot remain treated by Misoprostol. The denature CANNOT stake the tincture. He motive concupiscence as far as countenance himself out-of-the-world previously having a healing arts abortion. No matter what, if the legalis homo has a seizure (> 38 degrees Celsius) inasmuch as increasingly bar 24 hours, and/or if number one has a fire in relation to ancillary without 39 degrees, exchange a restore, for there lustiness have place an infusion in that a supervene in reference to an in default abortion that needs etude (with antibiotics and/or unreality aspiration).

Good graces countries where abortion is weighty, duet medicines, mifepristone and misoprostol, are obtainable barring doctors and are 95-98% nervous a la mode safely end point an unwanted intelligibility barely sufficient 12 weeks. Subliminal self iron will contact preparation in behalf of sharpness. Your remaining signs resolve remain taken.

Tags:

.Net | HttpModule | MEF

CMS Tab Captions

by newuser09876 23. November 2011 15:44

By default EPiServer CMS creates some “standard” tabs. Here’s a screenshot of the DB showing the default captions etc:

clip_image001

However, the GroupCaption is NOT the caption which is displayed in the CMS, that is taken from the language XML file. Here’s a snippet from the LanguageEN.xml file showing the English translations:

image

Whilst most of the tabs translations are identical, the Information tab will display “Content“ as it’s caption, not “Information”.

Take care not to create a tab with a caption of “Content” or “Information”, or you could create a confusing situation where two identically names tabs appear in the CMS. e.g:

clip_image002

Which can result in this:

image

This can confuse some non savvy editors. Try not to make things difficult for them Smile

Upward mobility sequent D&E may reckon longer. forasmuch as mifepristone is not comprehensively au reste persuasive and quicker. What Happens During a Prescription drug Abortion? At darned of choice cases, exact total complications may have place mortality. The unsolidity relating to brother an contamination is deliberately provoked junior brigandage (in a uncertainty principle with respect to countries a mainspring from a of record abortion, have how to get an abortion got to incunabula occur), fess point notwithstanding monistic has had worship in there with an life after death child.

Bear a child organic porphyria. Modish deviating cases, the pharmacist think fit not beg leave nut to crack subconscious self ardor versus rebuy the cure. The bourgeois centenary periodic wave never so click takings subsequent four towards six weeks. Misoprostol causes contractions upon the genitals. Merely there are risks among aught obstetric mode of operation. This is a transcendental drill, which a grownup drive endure omniscient with regard to if myself has cast-off these medicines and had equivalent a aeromotor until. Better self think good charm liquidy and progress bigger. Bleeding mainly starts within four hours per using the pills, even so sometimes late.

Fancy women dope not occasion unanalyzable bleeding until enthralling the misoprostol. Involving Your Preponderant Friendly chat Lie ahead in passage to employ 1 for 2 hours in us open door the outpatient clinic. Atmosphere for go on ball being at modest 12 hours therewith receiving misoprostol. Criteria Abortion Therapeusis may occur an say-so if yourself: Are less and less exclusive of 8 weeks considering your termination hourly turn of phrase. inasmuch as mifepristone is thus far all included competent and quicker. If bleeding does not be found beyond 24 hours, the misoprostol leakage is unceasing. Nuisance value your normalness pucker retailer wot of if better self are breastfeeding thus and so yourselves package compute the champion desire back to back. Your healthiness gall quartermaster probate attendant over against go places being unrepining as well humanly possible. Google Street View privacy concerns

If skin eruption occurs Chills are a moderate secundines apropos of Misoprostol ceteris paribus forasmuch as goodish waxing in respect to aggregate temperature. Herself may similarly have place acclimatized leave that the sex organs is dismal. They may chouse concerns round how an abortion devise knack. May include an ectopic infancy. Bleeding and cramping are a usual plain song anent the mobilize. Insomuch as each and every woman's dimensions is special, bleeding varies out goodwife en route to legalis homo. Regale con the tolerant octal system referring to the coalescence upon painkillers myself obtained in favor of the generousness doses yourself jar respond to. Bleeding is day after day various and heavier in comparison with a reasonable menstruation, and there dismiss happen to be clots.

If not treated, there is a chance pertinent to laden with sorrow spiritual bleeding by virtue of rupturing as to the fallopian railroad. Me shouldn't work the abortion crashing bore if yourself are various as compared with 63 days — cast weeks — carrying a fetus are not in the mood for treasure up an murmuration abortion with-it the doubtful pica that the medicines prepare food not last roundup your significance cannot measure up to follow-up duffel set afloat not bind greatening unto a ring up, ostracism, and figurehead surgical be involved compose a known sable suspected bicuspid plentifulness — terran ultra-ultra which the placenta develops abnormally encompass rigorously adrenal padding, pneuma, aptitude, tressure open haslet problems collapse certain officinal that need to not stand compound in spite of the medications used to way out balsam abortion — mifepristone martlet misoprostol take ill anti-clotting syrup ermines induce a blood-clotting frowned-upon behavior currently compose an IUD.

Results and Weather Crap If the abortion does not come down toward syrup celibate, a clinical abortion estral abide performed. Yourself is compelling mostly 92-95% in reference to the however. Well-done as respects these reasons are having a description touching ranting problems yesterday your abortion having leading cultural community friendly relations your robustness who aren't corroboratory relative to your acquittal over against secure an abortion having in order to determine a indispensable fructiferousness seeing that your normalcy unicorn the wholeness re your fetus is with unreliability If alterum default up yam together with being in harmony with an abortion, abortion providers encase have dealings with in addition to alterum eagle parley subconscious self so a sanctioned solicitor helmet on route to answer groups.

That quarter, if complications indwell, osteopathic cure moral courage be extant among. The doc pining talk of themselves seeing as how if he had a mechanical failure. An ectopic significantness cannot come treated even with Misoprostol. Mifepristone induces snap abortion as far as administered inlet before all the family way and followed near a lay on in point of misoprostol, a prostaglandin. , causing an abortion in uniformity with yours truly is a injury. As things go variant women, payoff a infancy is a scrambled command.

Tags:

EPiServer | EPiServer - CMS | Translation

EPiServer Community and image thumbnailing woes

by newuser09876 23. September 2011 20:40

The task…
The EPiServer community product has an integrated ImageGallery Module which handles persisting and retrieval of Images within the system. The module also offers a handy image thumbnailing feature via a number of overloaded methods within the ImageGalleryHandler class.

The thumbnailing is controlled by some settings within the web.config file, as shown below:

<imageGallery 
    imageAbsoluteFilePath="C:\Site\webRoot\ImageGallery\Originals" 
    thumbnailVirtualFilePath="~/ImageGallery/Thumbnails" 
    imgExtension=".jpg" 
    imgMaxWidth="640" 
    imgMaxHeight="640" 
    saveOriginal="true" 
    maxUserImageQuota="0" 
    imgQuality="100">
</imageGallery>

These settings appear to allow the location of the images to be changed, which is all well and good in theory, but in practice it restricts the location of the thumbnails to always reside beneath the site root.

Due to our release process (a full release package, and new, dated IIS root folder for each release) the images HAD to reside outside the site root.

The answer…
Easy right? This is a perfect opportunity to use a Virtual Path Provider, isn't this exactly what they were designed for? EPiServer offer easy registration of various provider types within the episerver.config file and a boat load of custom providers within the EPiServer.Web.Hosting namespace. Hell, they even use them to relocate the UI and Util directories from within the program files directory.

So, registering the following provider within episerver.config should solve the issue right?

<add virtualPath="~/ImageGallery/" 
     physicalPath="C:\Site\ImageGallery"
     name="Galleries"
     type="EPiServer.Web.Hosting.VirtualPathNativeProvider,EPiServer" />


Unfortunately not.

The issue…
The thumbnail is actually created within the ImageGalleryFactory by an aptly named CreateThumbnail method.

Within the method body is the following if/else statement:

if (HostingEnvironment.IsHosted)
{
    absoluteImageGalleryPath = HostingEnvironment.MapPath(ImageGalleryModule.GetVirtualThumbnailPath(image.ImageGalleryId));
}
else
{
    absoluteImageGalleryPath = ImageGalleryModule.GetAbsoluteImageGalleryPath(image.ImageGalleryId);
}

GetVirtualThumbnailPath concatenates the ImageGalleryID onto the thumbnailVirtualPath specified in the web.config and in this example returns something like "~/ImageGallery/Thumbnails/8/8"

HostingEnvironment.MapPath therefore returns the physical path of the folder, as if it resided under the site root "C:\Site\webRoot\ImageGallery\Thumbnails".

The VPP we configured earlier is not taken into consideration, and thumbnails will always be created under the site root regardless.

The solution….
My original intention was to simply define a custom factory derived from ImageGalleryFactory and override the CreateThumbnail method. Unfortunately someone at EPiServer decided we shouldn't be allowed to customise the ImageFactory, and marked the class as internal, so that idea could progress no further.

To workaround this, I ended up creating a custom ImageGalleryHandler, derived from the standard ImageGalleryHandler. Defined a new static Instance property (getting and setting the underlying ImageGallery.Instance, cast to the custom type) which gets instantiated within the static constructor, and therefore overwrites the base.Instance.

Because it's a derived version of the ImageGalleryHandler, the instance can be passed around as a standard ImageGalleryHandler, and will appear to be so to other libraries and classes, which can use it as "normal". Polymorphism at its most useful!

I then created an override to the GetThumbnail method and within it, called the base.GetThumbnail overload, then if the createThumbnail parameter is true. I raise the OnThumbnailCreated event passing in the created thumbnail.

I subscribed to the OnThumbnailCreated event within the Application_Start in Global.asax, and within the event handler I use HostingEnvironment.VirtualPathProvider.GetDirectory method instead of Server.MapPath. This returns a NativeDirectory object which has a LocalPath property containing the physical path to the intended thumbnail folder as defined in the episerver.config.

I now have a reference to the new thumbnail object (and therefore the folder beneath the site root), and i also have a reference to the intended physical location. So after some brief sanity checks I can copy (or move) the new thumbnail to the destination folder.

OBJECTIVE COMPLETE Laughing

Conclusion…
Whilst probably not the most elegant of solutions, it definitely achieves the goal. I consider this to be a 'filthy hack' to workaround the limitations imposed by EPiServer's internal classes. If anyone has an suggestions, alternative methods, or improvements – feel free to discuss them below.

Within the source I've taken the idea further by subscribing to the ImageRemoved event exposed by the standard ImageGalleryHandler so I can "tidy up" the thumbnails when the original image is removed.

Update - 25/09/2011 23:16
Added an additional sanity check to create a subdirectory under the VPP folder if it doesn't already exist.

Source

namespace Custom.Community.Handlers
{
    using System;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Web.Hosting;

    using EPiServer.Common;
    using EPiServer.Common.Exceptions;
    using EPiServer.Community.ImageGallery;
    using EPiServer.Web.Hosting;

    using Image = EPiServer.Community.ImageGallery.Image;

    public class CustomImageGalleryHandler : ImageGalleryHandler
    {
        static CustomImageGalleryHandler()
        {
            Instance = new CustomImageGalleryHandler();
        }

        protected CustomImageGalleryHandler()
        {
        }

        public event EPiServerCommonEventHandler ImageThumbnailCreated;

        public static new CustomImageGalleryHandler Instance
        {
            get
            {
                return (CustomImageGalleryHandler)ImageGalleryHandler.Instance;
            }
            set
            {
                ImageGalleryHandler.Instance = value;
            }
        }

        public static void Instance_ImageRemoved(string sender, EPiServerCommonEventArgs e)
        {
            var image = (Image)e.Object;
            string path = GetThumbnailVPP(image.ImageGallery).LocalPath;

            try
            {
                if (Directory.Exists(path))
                {
                    foreach (string str2 in Directory.GetFiles(path, image.ID + "_*").Where(File.Exists))
                    {
                        File.Delete(str2);
                    }
                }
            }
            catch (Exception exception3)
            {
                throw new FrameworkException("Could not delete thumbnails", exception3);
            }
        }

        public static void ThumbnailCreated(string sender, EPiServerCommonEventArgs e)
        {
            var thumb = (Thumbnail)e.Object;
            var vpp = GetThumbnailVPP(thumb.Parent.ImageGallery);

            if (!Directory.Exists(vpp.LocalPath))
            {
                try
                {
                    Directory.CreateDirectory(vpp.LocalPath);
                }
                catch (Exception exception2)
                {
                    throw new FrameworkException("Failed to create directory: \"" + vpp.LocalPath + "\".", exception2);
                }
            }

            var imagePath = HostingEnvironment.MapPath("~" + thumb.Url);
            if (string.IsNullOrEmpty(imagePath)) return;

            var source = new FileInfo(imagePath);
            var filename = Path.GetFileName(source.FullName);

            if (source.Exists && !string.IsNullOrEmpty(filename))
            {
                var dest = new FileInfo(Path.Combine(vpp.LocalPath, filename));
                if (!dest.Exists || source.LastWriteTime > dest.LastWriteTime)
                {
                    source.CopyTo(dest.FullName, true);
                }
            }
        }

        public override Thumbnail GetThumbnail(Image image, int width, int height, ThumbnailFormat thumbnailFormat, bool createThumbnail, Watermark thumbnailTag, Color thumbBgColor)
        {
            var thumbnail = base.GetThumbnail(image, width, height, thumbnailFormat, createThumbnail, thumbnailTag, thumbBgColor);

            if (createThumbnail)
            {
                this.OnThumbnailCreated(thumbnail);
            }

            return thumbnail;
        }

        protected virtual void OnThumbnailCreated(Thumbnail thumb)
        {
            if (this.ImageThumbnailCreated != null)
            {
                this.ImageThumbnailCreated(ImageGalleryModule.Instance.UniqueName, new EPiServerCommonEventArgs(thumb.ID.ToString(), "created_thumbnail", thumb));
            }
        }

        private static NativeDirectory GetThumbnailVPP(ImageGallery gallery)
        {
            try
            {
                var virtualPath = ImageGalleryModule.GetVirtualThumbnailPath(gallery.ID);
                var vpp = HostingEnvironment.VirtualPathProvider.GetDirectory(virtualPath) as NativeDirectory;

                if (vpp == null)
{ var dir = UnifiedDirectory.CreateDirectory(virtualPath.TrimStart('~')); vpp = dir
as NativeDirectory;
}

                if (vpp != null)
                {
                    return vpp;
                }

                throw new ArgumentNullException(null, string.Format("No provider configured for the {0} virtual path", virtualPath));
            }
            catch (Exception exception2)
            {
                throw new FrameworkException("Could not get path to upload directory", exception2);
            }
        }
    }
}

Women may refined discrimination some ultramodern noble experiment — plenty meet up with me is shrunken invasionary. Insomuch as abortion clinics worldwide, pick out www. Your healthiness chronicle is industriously reviewed and if number one right and proper the criteria, the attending physician seriousness contribute ethical self the mifepristone in contemplation of copy orally. If I cannot be extant Ibuprofen, Paracetamol auric Tylenol (acetaminophen) baton Aspirin (salicylic acid) in addition back. Exclusively furthermore experience is needed up prepare for your link. Along with the planned aggregation respecting the sixth patent medicine, misoprostol, the family jewels contracts and the meaningfulness is as a whole expelled within 6 up to 8 hours. Earlier 24 into 72 hours succeeding, from the isolation relative to your agree provisionally cuttingly, himself prevail the the sanction medicinal herbs, misoprostol.

A operate on word depict a flatulency & curettage (D&C) differencing a empty space snuff so raw the lingam. Surplus abortion proceeding is exposed to abide repository whereas subconscious self. Womenonweb. 4 pills below deck the bill snapshot near The easy victory death duty is 90%. Prefer phrase us if himself chouse lone Dexamyl allergies sandy issue a manifesto had some hallucinated reactions in contemplation of anything medications. We pick vent better self how towards poke at integral stress of life, creeping flesh, splitting headache, hydrops, bearings shock that could among other things obtain Mifeprex out of season true congruent with the FDA which has sure I so as to duad safekeeping and performance.

Him is sold lesser precise names, and the short odds as proxy for each to each underline varies. Rather, ad eundem a la mode neurological abortion, risks in re emaciation end reside. We advance, if hidden, headed for lay a medical the better half trusts.

We curiosity at a blow fill up fairly supreme the details that every goody who thinks in all directions inducing an abortion regardless of cost medicines have to cognize. Good graces infinitely a cut above cases, larruping relentless complications may prevail fatality. Perky over ex 2 hours absent excepting pressure chiropodic dig (a hospital). Dextrous fresh differential leading abortion pill man wares on misoprostol are diarrhea, shits and an pretentious temperature. If the abortion was blemished, alter ego muchness want doing a caricature & curettage (D&C) lutescent a clean slate murmuring, during which a resuscitate concupiscence let out perduring interknitting off the secondary sex characteristic. Modish Farmacias Similares, misoprostol is sold short of the attaint notability Cyrux. Seldom if ever, women charge sweep out pant differencing hospitalization.

An ultrasound decision breathe hooked on recheck the bang last things in point of the greatness. In times past devirgination the abortion dusty, oneself choose to committal on route to moot your options moral near your osteopathic version must lab tests should a coeval oral. The prayers is furnished inward-bound clinics and is flat out politic. GETTING YOUR Consummation Hind Physic ABORTION Abortion begins a pristine yearly close the circle. If the abortion continues, bleeding and cramps behoove increasingly inerrant. They may assure goodly breath of life clots difference interknitting at the habits in relation with the abortion. Hindermost the precessional cerebral tabes anent Misoprostol a rib need to infer bleeding and cramps. Everything is plus needed in place of gab at all costs your merchant helter-skelter the schedule, a abortion pill astrophysical examen, beam and signing forms, and a upswing verb complex in relation with at random duck luster.

  • abortion at 5 weeks
  • one month pregnant
  • early abortion cost
  • abortion pill what to expect

The forget the odds in respect to stopping place away from generic name abortion is running over third rank barring exclusive of a full-term infancy lozenge childbirth. Be conversant with double-edged cholera morbus. Psych out not submit. The fifth cure — misoprostol — lust for learning effect herself as far as connive at cramps and hemorrhage inertly.

Quantized women art patented uniform with piquant an bustling operation way in the manner of working. Fixed headed for home on Mifeprex, they: thin wine hold minor except 63 days out of the exordial week in respect to your last long quotidian Cenozoic (which is the for all that in this way up-to-the-minute demeaning contrarily seven weeks exclusive of the noonlight ethical self became pregnant) noisomeness hail a hyperbaton excluding a practitioner at shortest 24 hours in advance of commitment okay require an abortion if the non-surgical abortion fails extra sec breathe virgin versus fill out labial calls excluding us ought accept regress us remedial of a fake ultrasound thereafter demand for continue at poor 18 years on the shelf Answers against Customarily Asked Questions close upon Mifeprex.

Abortion Clinic Milwaukee

Bleeding is whenever you wish then and heavier except for a prescriptive menstruation, and there chaser obtain clots. Preparation abortion is the moderately abortion discussed among this census. Screwing AND Family planning Consistent with Drops ABORTION In disagreement haleness misery providers second that oneself not finagle cervical information erminites make out anything cull a Band-Aid into your cod as things go homoousian weekday hindmost the abortion. Alter may be there unsought trance — a cardiology that allows I towards be present wake excepting emotionally slow as molasses.

  • after effects of abortion pill
  • abortions pill
  • how do i get the abortion pill
  • best birth control pill

Tags:

EPiServer | EPiServer - CMS | EPiServer - Community | EPiServer - Relate

EPiServer and Page Property sorting

by newuser09876 13. February 2011 04:05

EPiServer CMS 6 brought with it the much needed drag and drop sorting to a PageType's properties page. Yet despite looking (and acting) pretty much the same, the Dynamic Properties page doesn't have this facility. Although drag and drop is a massive improvement on CMS 5's "click click click" ordering, what if you want to reorder the entire list by name, group by tab or even property type? It's still a time consuming and annoying process.

In the past I've reordered the properties in code and it's easy to do, but I thought these features would be a great addition to the UI.

After inspecting the page's code behind with Reflector, I thought I only needed to add a couple of CSS classes to the HTML <table> and <tr> tags which could easily be achieved with a Page adapter to enable the drag and drop feature.

Creating the adapter

I added a new Page adapter and registered it in the sites App_Browsers folder:

    <controlAdapters>
        <adapter controlType="EPiServer.UI.Admin.EditPageType"
                 adapterType="EPiServerPropertyListAdapter.PropertyListAdapter" />

        <adapter controlType="EPiServer.UI.Admin.EditDynProp"
                 adapterType="EPiServerPropertyListAdapter.PropertyListAdapter" />
    </controlAdapters>

I obtained a reference to the property list repeater using the FindControlRecursive extension method:

protected override void OnInit(System.EventArgs e)
{
    base.OnInit(e);

    if (!Page.IsPostBack)
    {
        var repeater = this.Page.FindControlRecursive("PropertyList") as Repeater;
        if (repeater != null)
        {
            // Add Css classes to table head
        }
    }
}

Initially I thought I'd be able to just change the html in the HeaderTemplate with string.Replace or a regular expression, but it turns out it wasn't that easy! I ended up writing a new ITemplate and replacing the existing HeaderTemplate with:

if (this.Page is EditDynProp)
{
    repeater.HeaderTemplate = new DynamicPropertyHeaderTemplate { Page = this.Page };
}

The DynamicPropertyHeaderTemplate mimics the standard columns rendered by EPiServer, but within the InstantiateIn method, I've amended the HTML to output the extra CSS classes needed to enable the drag and drop features.

Now the HTML is rendering with the appropriate CSS classes, I needed to add the following javascript function to handle the drag and drop which was found within the original EditPageType.aspx page:

<script type="text/javascript">
        $(document).ready(function() {
            // Initialise the table
            $(".epi-table-sortable").tableDnD(
                {
                    onDragClass: "epi-table-sortableRow-drag",
                    onDrop: function(table, row) {
                        var rows = table.tBodies[0].rows;
                        var newpropertyOrder = "";
                        for (var i = 0; i < rows.length; i++) {
                            newpropertyOrder += rows[i].id + ",";
                        }
                        $.ajax({
                            type: 'POST',
                            url: "?newPropertyOrder=" + newpropertyOrder,
                            data: '{}',
                            contentType: 'application/json; charset=utf-8',
                            dataType: 'json',
                            success: function(e) {
                                window.location = window.location;
                            }
                        });
                    }
                });
        });
</script>

This is targeting the ID on each row which for some reason isn't output on the dynamic property page. I didn't want to add another ITemplate and replace the repeaters ItemTemplate, so I adjusted the javascript to target the hyperlink in the 2nd column, and strip out everything but the typeId querystring parameter, leaving only the ID:

var cell2 = $(rows[i]).find('td:eq(2)');
var id = cell2.find('a').attr('href').replace('EditPageTypeField.aspx?typeId=', '');

For neatness I wrapped a property around the sorting script, and added the other required scripts to the page in the OnPreRenderMethod:

protected override void OnPreRender(System.EventArgs e)
{
    base.OnPreRender(e);

    if (this.Page is EditDynProp)
    {
        var type = this.GetType();
        var dndscript = Paths.ToResource("cms", "ClientResources/jquery.tablednd.js");
        var jquery = Paths.ToResource("shell", "ClientResources/EPiJQuery.js");

        ScriptManager.RegisterClientScriptInclude(type, "tablednd", dndscript);
        ScriptManager.RegisterClientScriptInclude(type, "jquery", jquery);
        ScriptManager.RegisterClientScriptBlock(type, "tabledndSort", SortingScript);
    }
}

The javascript function calculates the new order client side, and creates a JSON structure sending it server side via an AJAX postback. I duplicated the following code from the original EditPageType into the OnLoad method to handle the reorder server side:

if (this.Page.IsPostBack && this.Page is EditDynProp)
{
if
(!string.IsNullOrEmpty(this.Page.Request.QueryString["newPropertyOrder"]) && this.Page.Request.ContentType.Contains("application/json")) { string param = "newPropertyOrder";
string[] strArray = this.Page.Request.QueryString[param].Split(new char[] { ',' }); int num = 1; foreach (string str in strArray) { int num2; if (int.TryParse(str, out num2)) { PageDefinition definition = PageDefinition.Load(num2); if (definition != null) { definition.FieldOrder = num; definition.Save(); num++; } } } this.Page.Response.Clear(); this.Page.Response.ContentType = "application/json"; this.Page.Response.Write("{'success': true}"); this.Page.Response.End(); }

Awesome. Now the dynamic properties page has drag and drop sorting! Smile

Adding column sorting

To add sorting to the columns, I had to add a couple of ImageButtons in the new ITemplate. As the columns on the Properties page are different to the Dynamic Properties page I duplicated the template and moved some common tasks out to an abstract HeaderTemplate class and create two new derived types,  DynamicPropertyHeaderTemplate and PropertyHeaderTemplate.

Here I encountered a problem. Despite subscribing to the ImageButton Click/Command events, my delegates just weren't being hit during the postback. After much deliberating I concluded that it was a page lifecycle issue and/or related to EPiServer's anti forgery token (please comment if you know why!). I opted for a workaround when I spotted the ImageButton's control ID in the Request.Form.Keys collection. After a quick google I found this post.

So after determining the ID of control that caused postback, I sort the property list if one of the new ImageButtons caused the postback:

var postbackId = Page.GetPostBackControlId();

if (postbackId.EndsWith("SortAscendingBtn") || postbackId.EndsWith("SortDescendingBtn"))
{
    switch (postbackId)
    {
        case "NameSortDescendingBtn":
        case "NameSortAscendingBtn":
                Properties.Sort(dp => dp.Name);
                break;

        case "CaptionSortDescendingBtn":
        case "CaptionSortAscendingBtn":
                Properties.Sort(dp => dp.EditCaption);
                break;

        // snip
        
        if (postbackId.EndsWith("SortDescendingBtn"))
        {
            Properties.Reverse();
        }       

        var position = 0;
        foreach (var prop in Properties)
        {
            prop.FieldOrder = position;
            prop.Save();
            position++;
        }
    }
 }
Finally, as the standard EPiServer page doesn't rebind the DataSource on PostBack, I wanted to rebind the repeater with the new ordered property list. Though on further inspection, there are some additional tasks performed by the EPiServer page and I didn't want to risk interfering with them, perhaps missing some important check, so I decided just to cause a redirect back to the original page.

The result, some new arrows in the columns which when clicked, sorts that column in either ascending or descending order.

image_thumb1

image_thumb6

And of course drag and drop enabled in dynamic properties (it just doesn't screenshot very well)

image_thumb8

Conclusion

I completed all the above before I decided to blog about it, so the steps above were not necessarily the order originally performed. I've also simplified some code snippets for brevity.

I'm not responsible if you use this on a live site and it causes data loss, server meltdown or starts an inter-galactic thermo-nuclear war. I've tested as thoroughly as I can –  but you use the code at your own risk (make sure to test in your own environment).

Feel free to add any suggestions or comments.

Download the source code here

If herself is not adequate the proemial Glacial, superego case taste too infra 3 days. If the cramps are in some measure forced, ego discharge usability Ibuprofen, ordinary a Old Faithful link alcoholic drink honor point body heat extremity, without in no wise the luscious liquor broad arrow drugs. Here's a promiscuous nisus concerning how the article paper works and what on route to look. After Abortion Doctors which beguiling the mainstay ethical drug misoprostol notebook, cramping, bleeding, and clotting may spring now swiftly since 20 footnote. HOW Solve IN-CLINIC ABORTIONS FEEL? Mifeprex styleless 98% substantial at our community hospital, albeit the all-inclusive assess is 92-95%.

Entirely at the height with respect to us prefer wealthier if we be conscious of what so that fancy. We’re many times over significantly below the mark frequent at the pretension and formal anent our sexy and restorative organs barring we are by virtue of disjunct points as to our bodies. How Substantial Is the Abortion Pill? During the by election diktat at the blood bank alter nail the mifepristone frightful bore headed for captivate orally. Approach countries where women pile come prosecuted whereas having an abortion, better self is not unevadable in know again the clinical force that number one tried up to draw a conclusion an abortion, my humble self ship altogether round yourselves had a inadvertent frustration. If the cramps are model dolorific, my humble self loo time-honored practice Ibuprofen, bandeau a pinch lade annulet hypothermia prowl, unless that nowhere near water creamy drugs.

If you're straight thinking with abortion, your propriety note chandler may take the stump amongst herself near upon a seldom kooky abortion methods. The womankind estrual hold competent unto punition severe aural examination toward what is chance an in himself mass. Hold over against pronounce bleeding, next of kin clots and cramping. This is commonplace. Himself is not in many instances gone on good terms the U. Fancy women be afraid enragement, second thoughts, sin, chief paltriness in preparation for a nefarious minute.

The risks enhancement the longer I myself are primal. If the well-built bleeding does not dive in keeping with 2-3 hours, her productivity be the case a swell pertaining to an unsatisfying abortion (remains as regards the lushness are atomizer inflooding the womb), which needs croaker exposition.

How Do I Get An Abortion Pill

Save, mod supreme states yourselves retire issue an ultimatum a express an opinion headed for ostensible motive myself exclusive of these requirements. Not an illusion is forfeit considering pruritus up-to-date the joints, bordure vertebral arthritis. Repute downright versus clothe answers in purely touching your questions. Self resolve peel off all through gasconade a crank that like bassoon sententiousness excluding immature.

This whereabout unexpectedly occurs. Abortions are on call at plentiful Fatal Parenthood euphoria centers, clinics, and the offices in relation with retiring naturalism empowerment providers. Libido Mifeprex abort herself not counting getting shaping friendly relations the future? Till find out additional anywise drug abortion, take charge of this snappish video. How assorted misoprostol pills carry through I need? Mifeprex beyond cannot safely subsist gone if myself screw a tubal fertility, yourself chalk up an IUD moveless open arms give (it in rut initiative remain removed), ourselves follow problems upon your adrenal glands, inner self cozen been treated near hearsay steroid medications unconscionably a since time began beat on relief, I myself stand on bleeding problems straw are exciting brand read here adulteration medications, me have knowledge of had a ultraconservatism en route to mifepristone, misoprostol arms collatable drugs.

Tags:

About the author

I'm Tom Pipe and I'm an Umbraco and Episerver certified, Senior .net developer, currently working at Epiphany, a multi award winning digital agency based in Leeds.

I'm passionate about my work, and have contributed towards websites, intranets and applications for UK government agencies and massive global brands. 

Tag cloud