<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Jafet Valdez</title><link href="http://world.optimizely.com" /><updated>2018-10-22T17:12:21.0000000Z</updated><id>https://world.optimizely.com/blogs/jafet-valdez/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Changing Display Options Programmatically</title><link href="https://world.optimizely.com/blogs/jafet-valdez/dates/2018/10/changing-display-options-programmatically/" /><id>&lt;p&gt;Hello World.&lt;/p&gt;
&lt;p&gt;Display Options are a great way for you to give your content editors the ability to change how blocks and other content are&amp;nbsp;displayed&amp;nbsp;when working with ContentAreas.&lt;/p&gt;
&lt;p&gt;But one thing&amp;nbsp;about Display Options&amp;nbsp;isn&amp;rsquo;t very intuitive - how do we as developers apply them to content programmatically? I&amp;rsquo;d like to put it out there how this can be achieved very easily.&lt;/p&gt;
&lt;p&gt;For this example I&#39;ve set up two Display Options - Half Width and Full Width. But our content starts without having one of these set.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/8e01a5e2eeb44dc6b206e65f94ff74bb.aspx&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;The Theoretical Stuff&lt;/h3&gt;
&lt;p&gt;One thing to remember is that the display options are not a part of the content itself. Instead it&#39;s&amp;nbsp;a setting on&amp;nbsp;a&amp;nbsp;&lt;strong&gt;&lt;em&gt;ContentArea&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;&lt;/em&gt; that the content has beend added to. More specifically a setting available on every &lt;strong&gt;&lt;em&gt;ContentAreaItem&lt;/em&gt; &lt;/strong&gt;that populates the&amp;nbsp;&lt;strong&gt;&lt;em&gt;ContentArea.Items&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;&lt;/em&gt; list.&lt;/p&gt;
&lt;p&gt;So in other words we need to work with the piece of content that has the &lt;strong&gt;&lt;em&gt;ContentArea&lt;/em&gt; &lt;/strong&gt;we want to modify as a property. In my example below I&#39;ve added a &lt;em&gt;&lt;strong&gt;ContentArea&lt;/strong&gt;&amp;nbsp;&lt;/em&gt;property called &lt;em&gt;&quot;MainContent&quot;&lt;/em&gt; to&amp;nbsp;the&amp;nbsp;&lt;a href=&quot;https://github.com/episerver/Quicksilver&quot;&gt;QuickSilver&lt;/a&gt;&amp;nbsp;&lt;em&gt;&lt;strong&gt;StartPage&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;The Code&lt;/h3&gt;
&lt;p&gt;Knowing that Display Options are set on a&amp;nbsp;&lt;em&gt;&lt;strong&gt;ContentAreaItem&lt;/strong&gt;&lt;/em&gt;, let&amp;rsquo;s look at the code!&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    var startPage = _contentRepository.Get&amp;lt;StartPage&amp;gt;(ContentReference.StartPage);
    var cloneStartPage = startPage.CreateWritableClone() as StartPage;

    // Select the correct item in whatever way you want.
    // You could for example match specific content by looking for ContentArea.Items.FirstOrDefault(x =&amp;gt; x.ContentLink == myContentReference)
    // This time I&#39;m just grabbing the first item in the ContentArea.
    var item = cloneStartPage?.MainContent?.Items.FirstOrDefault();

    if (item != null)
    {
        item.RenderSettings[&quot;data-epi-content-display-option&quot;] = &quot;half-width&quot;; // &quot;half-width&quot; being the Id for a DisplayOption that we&#39;ve setup in our DisplayOptions
        cloneStartPage.MainContent.IsModified = true;
        _contentRepository.Save(cloneStartPage, SaveAction.Publish, AccessLevel.NoAccess);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s pretty simple but there are a couple of things here that are note worthy. First of all is the use of &lt;strong&gt;&lt;em&gt;ContentAreaItem.RenderSettings&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;dictionary instead of the now obsoleted &lt;em&gt;&lt;strong&gt;ContentAreaItem.DisplayOption.&amp;nbsp;&lt;/strong&gt;&lt;/em&gt;&lt;strong&gt;&lt;/strong&gt;It&#39;s a doozy of a dictionary key to remember, but hopefully it&#39;ll be setup as a constant somewhere some time soon. Or you can just refer back to this blog post.&amp;nbsp;&lt;img src=&quot;/Scripts/tinymce/plugins/emoticons/img/smiley-wink.gif&quot; alt=&quot;wink&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Either way, the second thing of note is that we explicitly set the &lt;strong&gt;&lt;em&gt;ContentArea.IsModified&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;property to true. Modifying the RenderSettings without doing any other change doesn&#39;t setup the &lt;em&gt;&lt;strong&gt;ContentArea&lt;/strong&gt;&lt;/em&gt; properly for whatever &lt;em&gt;(probably performance&amp;nbsp;related)&lt;/em&gt; magic that the &lt;strong&gt;&lt;em&gt;ContentRepository.Save&lt;/em&gt;&lt;/strong&gt; method does to determine what gets updated in the database and what doesn&#39;t.&lt;/p&gt;
&lt;p&gt;So if we ommit that line and save our page nothing will have changed after we&#39;ve run our code. But adding it and then saving will properly update&amp;nbsp;the display option on our piece of content:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/f1df73ceadc94ce5bc711ac38b4552b3.aspx&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Related&amp;nbsp;Reading Material&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;/link/ef6c9f676b214985a4c8ff489642c0fa.aspx&quot;&gt;How to setup DisplayOptions&lt;/a&gt;&lt;/p&gt;</id><updated>2018-10-22T17:12:21.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Curing your Redirect woes when using ASP.NET Identity and UISignInManager.SignIn()</title><link href="https://world.optimizely.com/blogs/jafet-valdez/dates/2018/9/curing-your-redirect-woes-when-using-uisigninmanager-signin/" /><id>&lt;p&gt;Hello World.&lt;/p&gt;
&lt;p&gt;In this post I&#39;ll show you how to&amp;nbsp;modify UISignInManager so that it does not fully rely on the ReturnUrl query parameter for redirects, enabling us to use whatever redirection logic we may desire and/or require!&lt;/p&gt;
&lt;h3&gt;The context&lt;/h3&gt;
&lt;p&gt;I recently ran into a thread here on World where a fellow developer had some issues with users being redirected to the sites&#39; root page (&amp;rdquo;/&amp;rdquo;) after&amp;nbsp;signing them in through a call to UISignInManager.SignIn().&lt;/p&gt;
&lt;p&gt;The intent was to redirect the users to&amp;nbsp;a specific&amp;nbsp;Url after signing them in. Sounds reasonable.&lt;/p&gt;
&lt;p&gt;But the issue with redirecting to another url after calling SignIn() is that the SignIn method already sets a redirect location on&amp;nbsp;the response, which means that you can try to redirect as much as you want afterwards. The user will still be redirected to whatever the SignIn() method decided to redirect to.&lt;/p&gt;
&lt;p&gt;And what does the SignIn()-method decide to redirect to? The ReturnUrl in the query parameters (for example &amp;rdquo;/Login?ReturnUrl=/ALockedPage&amp;rdquo;).&lt;/p&gt;
&lt;p&gt;This is fine in most cases where you, for example, get redirected to the login page for trying to access a page where users need to be authenticated. But what happens if you don&amp;rsquo;t have a ReturnUrl query paremeter set? Well it will simply redirect to &amp;rdquo;/&amp;rdquo; &amp;ndash; in other words, the sites&amp;rsquo; root page. This may not be what you want in all cases, especially if you have a custom login page with custom redirection logic.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; This SignIn() redirect also overrides redirects that you do&amp;nbsp;in the OnResponseSignIn Action in your OWIN configuration (a.k.a. Startup.cs).&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;So how do we solve this?&lt;/h3&gt;
&lt;p&gt;Well, we create our own UISignInManager of course!&lt;/p&gt;
&lt;p&gt;In this approach we&#39;ll modify the SignIn method so that it doesn&#39;t automatically redirect to sites&#39; root page if we do not have a ReturnUrl set.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    public class MyApplicationUISignInManager&amp;lt;TUser&amp;gt; : ApplicationUISignInManager&amp;lt;TUser&amp;gt; where TUser : IdentityUser, IUIUser, new()
    {

        protected ApplicationSignInManager&amp;lt;TUser&amp;gt; _signInManager;

        public MyApplicationUISignInManager(ServiceAccessor&amp;lt;ApplicationSignInManager&amp;lt;TUser&amp;gt;&amp;gt; signInManager) : base(signInManager)
        {
            _signInManager = signInManager();
        }

        public override bool SignIn(string providerName, string userName, string password)
        {

            if (HasReturnUrl()) // Use the default implementation if we have a ReturnUrl set
                return base.SignIn(providerName, userName, password);

            return _signInManager.SignIn(userName, password, null);
        }

        private bool HasReturnUrl()
        {
            return HttpContext.Current?.Request.QueryString?.Get(&quot;ReturnUrl&quot;) != null;   
        }


        /// &amp;lt;summary&amp;gt;
        /// Creates an instance of MyApplicationUISignInManager. Mainly for setting up the IoC Container.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&quot;options&quot;&amp;gt;&amp;lt;/param&amp;gt;
        /// &amp;lt;param name=&quot;context&quot;&amp;gt;&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
        public new static UISignInManager Create(IdentityFactoryOptions&amp;lt;UISignInManager&amp;gt; options, IOwinContext context)
        {
            return new MyApplicationUISignInManager&amp;lt;TUser&amp;gt;(context.Get&amp;lt;ApplicationSignInManager&amp;lt;TUser&amp;gt;&amp;gt;);
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this case, we only want to modify what happens if we do not have a ReturnUrl. So if we have a query parameter named ReturnUrl, we just use the standard UISignInManager code to handle that case. Otherwise we sign the user in ourselves without specifying a return url.&lt;/p&gt;
&lt;p&gt;Now we need to setup our IoC to use our new UISignInManager.&lt;/p&gt;
&lt;p&gt;This can be done in your Startup.cs file, just after you call the built in AddCmsAspNetIdentity() where all the default Managers and Providers are setup.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    // Example Startup.cs class
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.AddCmsAspNetIdentity&amp;lt;ApplicationUser&amp;gt;();

            app.CreatePerOwinContext&amp;lt;UISignInManager&amp;gt;(MyApplicationUISignInManager&amp;lt;ApplicationUser&amp;gt;.Create); // &amp;lt;-- Add this line after calling app.AddCmsAspNetIdentity

            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString(&quot;/Util/Login.aspx&quot;),
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity =
                        SecurityStampValidator
                            .OnValidateIdentity&amp;lt;ApplicationUserManager&amp;lt;User&amp;gt;, User&amp;gt;(
                                TimeSpan.FromMinutes(30),
                                (manager, user) =&amp;gt; manager.GenerateUserIdentityAsync(user)),
                    OnApplyRedirect = context =&amp;gt; context.Response.Redirect(context.RedirectUri),
                    OnResponseSignOut = context =&amp;gt; context.Response.Redirect(&quot;/ByeWorld&quot;),
                    OnResponseSignIn = context =&amp;gt; context.Response.Redirect(&quot;/HelloWorld&quot;) // This now works too! Yay!
                }
            });
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt;&amp;nbsp;In my example I call a static Create method that lives in my own implementation of UISignInManager, this is so that it&amp;rsquo;s done in a similar fashion to how the others defaults are setup in case you set them up manually instead of calling AddCmsAspNetIdentity().&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;re set and can start redirecting to whatever you want, either through the OnResponseSignIn action or manually after signing in users through UISignInManager.SignIn()! &#128522;&lt;/p&gt;</id><updated>2018-09-20T01:14:11.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Tools of the Trade - Diagnosing orders with errors</title><link href="https://world.optimizely.com/blogs/jafet-valdez/dates/2018/6/tools-of-the-trade---diagnosing-orders-with-errors/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;Hello world.&lt;/p&gt;
&lt;p&gt;Welcome to my first blog post here on Episerver World! :D&lt;/p&gt;
&lt;p&gt;Today I thought that I&amp;rsquo;d share one of my most commonly used tools to diagnose and debug errors on PurchaseOrders or Carts.&lt;/p&gt;
&lt;h3&gt;First a little bit of background&lt;/h3&gt;
&lt;p&gt;For the last couple of years, I&amp;rsquo;ve been involved in a project that has had some pretty complicated order handling logic. It has advanced return and exchange handling, different payment providers, different shipping methods, split shipments and multi warehouses while also having integrations on many of these processes that could fail for whatever reason.&lt;/p&gt;
&lt;p&gt;With so many processes being able to affect an order in various stages there has unfortunately been some cases where an order has come out the other end all weird looking. Maybe this weirdness manifested itself in a button being disabled unexpectedly, a return failing to be processed even though it shouldn&amp;rsquo;t, some data missing or things of that nature.&lt;/p&gt;
&lt;h3&gt;So what is this &quot;Tool of the trade&quot;?&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s a very simple tool, really. Just some SQL SELECT queries that gathers up all the relevant information for an order in one place. While Commerce Manager is great in many ways in terms of displaying information, it still doesn&amp;rsquo;t display all the possible fields that could be relevant for you when you have your detective hat on.&lt;/p&gt;
&lt;p&gt;Alright no more talking, here it is:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;DECLARE @OrderGroupId int = &#39;12345&#39; -- Set this to the ordergroupId of the order you want to inspect

SELECT *
FROM OrderGroup og
JOIN OrderGroup_PurchaseOrder po ON og.OrderGroupId = po.ObjectId
WHERE og.OrderGroupId = @OrderGroupId
-- or you can JOIN OrderGroup_ShoppingCart instead if you want to inspect Carts

SELECT * 
FROM OrderForm oform
JOIN OrderFormEx ofex ON oform.OrderFormId = ofex.ObjectId
WHERE oform.OrderGroupId = @OrderGroupId

SELECT *
FROM Shipment sh
JOIN ShipmentEx shex ON sh.ShipmentId = shex.ObjectId
WHERE sh.OrderGroupId = @OrderGroupId

SELECT *
FROM LineItem l
JOIN LineItemEx lex ON l.LineItemId = lex.ObjectId
WHERE OrderGroupId = @OrderGroupId
ORDER BY LineItemOrdering ASC

SELECT *
FROM OrderGroupAddress oga
JOIN OrderGroupAddressEx ogae ON oga.OrderGroupAddressId = ogae.ObjectId
WHERE oga.OrderGroupId = @OrderGroupId

-- Add SELECTs for as many payment types that an order can have:

SELECT *
FROM OrderFormPayment ofp
JOIN OrderFormPayment_Other ofpex ON ofp.PaymentId = ofpex.ObjectId
WHERE ofp.OrderGroupId = @OrderGroupId

SELECT *
FROM OrderFormPayment ofp
JOIN OrderFormPayment_GiftCard ofpex ON ofp.PaymentId = ofpex.ObjectId
WHERE ofp.OrderGroupId = @OrderGroupId

/*
For payments you can JOIN these tables:

OrderFormPayment_Other
OrderFormPayment_GiftCard
OrderFormPayment_CashCard
OrderFormPayment_CreditCard
OrderFormPayment_Invoice
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pretty simple really. Based on an OrderGroupId we get data about the OrderGroup, all the OrderForms (including &amp;ldquo;ReturnForms&amp;rdquo;), Shipments, LineItems, OrderAdresses and Payments. On all the levels of abstraction you also get their additional metadata that you&amp;rsquo;ve added joined up, so it&amp;rsquo;s all in one convenient place for you to inspect.&lt;/p&gt;
&lt;p&gt;Obviously, you&amp;rsquo;ll need to find a way to retrieve the OrderGroupId before putting it into this query. I&amp;rsquo;m actually running a bit more complicated version where I can use a custom order tracking number and an id from our main payment provider to retrieve the order data instead of an OrderGroupId. I omitted that in what I shared above because it&amp;rsquo;s not really general enough to be used by everyone.&lt;/p&gt;
&lt;h3&gt;Ok, now I can see the data, what do I do with it?&lt;/h3&gt;
&lt;p&gt;What I look for are oddities. This could maybe be a field missing a value because it got nulled away in some dark corner of a Workflow. Or maybe a string MetaField containing serialized data that got cut off because you didn&amp;rsquo;t expect that a customer would ever use THAT many bonus checks.&lt;/p&gt;
&lt;p&gt;Either way, after you&amp;rsquo;ve used this query in various stages of your order processing flow you&amp;rsquo;ll develop a feel for what seems out of place for orders in your project.&lt;/p&gt;
&lt;h3&gt;My orders never have any issues, any other use cases?&lt;/h3&gt;
&lt;p&gt;First, I&amp;rsquo;d like to say that I&amp;rsquo;m impressed! :D&lt;/p&gt;
&lt;p&gt;Secondly, here&amp;rsquo;s some other examples of where I use this query:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Teaching the structure of Carts/PurchaseOrders in Episerver Commerce to new developers.&lt;/strong&gt;&lt;br /&gt; This is kind of a nerdy approach, but it&amp;rsquo;s been&amp;nbsp;very useful&amp;nbsp;so far. Most developers are used to the database way of structuring things. Showing the data and structure like this I can explain what each level of abstraction is responsible for and what data they contain, but also the fact that the system is extensible because you can add your own meta fields.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;While developing new order handling features&lt;/strong&gt;&lt;br /&gt;I can use this to make sure that the database is correct along the way and spot any unexpected issues with the data being stored.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;When joining a new project that&amp;rsquo;s been going on for a while.&lt;/strong&gt;&lt;br /&gt; It&amp;rsquo;s useful to get details on what meta fields have been added so that you know what you have to work with. This of course also reduces the risk of you adding a field that stores the same data as an existing one.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;But hey, don&amp;rsquo;t take my word for it!&lt;/h3&gt;
&lt;p&gt;Me and my colleagues have used it extensively, but I actually got inspired to share this more publicly after helping a fellow Episerver Developer on the forums figure out why a button in Commerce Manager didn&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the thread:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;/Modules/Forum/Pages/Thread.aspx?id=194165&quot;&gt;https://world.episerver.com/Modules/Forum/Pages/Thread.aspx?id=194165&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thanks for reading! I hope that this will help you in your diagnosing and debugging endeavors!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jafet &amp;ldquo;Jeff&amp;rdquo; Valdez&lt;/em&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2018-06-17T15:47:31.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>