<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sitecore &#8211; SymSoft Solutions</title>
	<atom:link href="https://www.symsoftsolutions.com/blog/topic/sitecore/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.symsoftsolutions.com</link>
	<description>High Performance Websites for Enterprises</description>
	<lastBuildDate>Fri, 05 Dec 2025 20:21:30 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>

<image>
	<url>https://www.symsoftsolutions.com/wp-content/uploads/2020/07/cropped-logo-square-32x32.png</url>
	<title>Sitecore &#8211; SymSoft Solutions</title>
	<link>https://www.symsoftsolutions.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>3 Key Takeaways from Sitecore Symposium 2025: What Public Sector Organizations Need to Know</title>
		<link>https://www.symsoftsolutions.com/sitecore/key-takeaways-from-sitecore-symposium-2025/</link>
		
		<dc:creator><![CDATA[Daniel Calzada]]></dc:creator>
		<pubDate>Fri, 05 Dec 2025 20:19:59 +0000</pubDate>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[Sitecore]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=13670</guid>

					<description><![CDATA[SymSoft Solutions had the privilege of presenting at Sitecore Symposium 2025 in Orlando, where we shared our transformative work with CAL FIRE in front of marketing leaders, technologists, and digital innovators. Our session, "No playing with fire: How CAL FIRE transformed emergency communication with Sitecore" showcased how California's Department of Forestry and Fire Protection upgraded its digital presence to meet the demands of emergency response in an increasingly challenging wildfire season.]]></description>
										<content:encoded><![CDATA[<p>SymSoft Solutions had the privilege of presenting at Sitecore Symposium 2025 in Orlando, where we shared our transformative work with CAL FIRE in front of marketing leaders, technologists, and digital innovators. Our session, &#8220;<em>No playing with fire: How CAL FIRE transformed emergency communication with Sitecore</em>&#8221; showcased how California&#8217;s <a href="https://www.fire.ca.gov/" target="_blank" rel="noopener">Department of Forestry and Fire Protection</a> upgraded its digital presence to meet the demands of emergency response in an increasingly challenging wildfire season.</p>
<p>Beyond sharing our success story, the symposium unveiled groundbreaking innovations with significant implications for California&#8217;s public sector. Here are three key takeaways that every digital leader in government would benefit from understanding.</p>
<h2>1. The Launch of SitecoreAI: Agentic Intelligence for the Public Sector</h2>
<p>Sitecore unveiled <a href="https://www.sitecore.com/company/newsroom/press-releases/2025/10/sitecore-unveils-sitecoreai-ushering-in-the-ai-first-era-of-digital-experience" target="_blank" rel="noopener">SitecoreAI</a>, a next-generation digital experience platform that positions artificial intelligence at the center of digital marketing and content delivery. Built on the foundation of Sitecore XM Cloud, this composable SaaS platform introduces the <a href="https://www.sitecore.com/company/newsroom/press-releases/2025/10/sitecore-launches-sitecore-studio-revolutionizing-customization-extensibility-and-co-innovation" target="_blank" rel="noopener">Agentic Studio</a>, a collaborative workspace where marketers and AI work together through 20 AI-powered agents that automate workflows from campaign planning to content migration, production, and testing.</p>
<h3>Why the California Public Sector Should Care</h3>
<p>While the private sector focuses on &#8220;marketing,&#8221; government agencies confront parallel challenges in constituent communication, public information management, and service delivery. California is already leading the nation in the responsible deployment of AI for government services, as evidenced by <a href="https://www.gov.ca.gov/2025/04/29/governor-newsom-deploys-first-in-the-nation-genai-technologies-to-improve-efficiency-in-state-government/" target="_blank" rel="noopener">Governor Newsom&#8217;s GenAI initiatives</a>. SitecoreAI&#8217;s agentic intelligence addresses the actual operational needs of government agencies:</p>
<h3>Content Operations &amp; Public Information:</h3>
<ul>
<li><strong>Legislative and policy updates</strong>: When regulations change, AI agents can help identify all affected pages across your site, draft updates based on official documents, and flag content requiring human review, transforming a weeks-long manual process into days.</li>
<li><strong>Emergency content deployment</strong>: During wildfires, public health emergencies, or natural disasters, AI agents can rapidly deploy pre-approved content templates, update incident information across multiple pages, and ensure consistent messaging.</li>
<li><strong>Multilingual content at scale</strong>: California serves constituents in dozens of languages. AI agents can accelerate translation workflows while ensuring culturally appropriate terminology, though human review remains essential for accuracy and nuance.</li>
<li><strong>Content migration</strong>: Moving from legacy systems to modern platforms  typically requires months of manual work. AI agents can automate much of this heavy lifting.</li>
<li><strong>Routine updates</strong>: AI can handle repetitive tasks like updating contact information, office hours, or program deadlines across multiple pages.</li>
<li><strong>Improved search results</strong>: AI-powered search that understands intent (e.g., &#8220;apply for assistance&#8221; vs &#8220;eligibility requirements&#8221;)</li>
</ul>
<h2>2. Moving Beyond the Website: Content Discovery in the Age of AI Summaries</h2>
<p>CEO Eric Stine emphasized a fundamental shift: <em>&#8220;We&#8217;re living in the world beyond the website. Discovery is no longer driven by search; it&#8217;s powered by attention. Brands earn that attention in social media feeds and AI-generated summaries when they show up in the right moment with the right message.&#8221;</em></p>
<p>Californians are increasingly finding government information through AI-powered search summaries, voice assistants, and social media rather than directly navigating to agency websites. This shift has massive implications for how public sector organizations deliver critical information.</p>
<p>At SymSoft, we&#8217;re already helping California agencies prepare for this multi-channel reality by building a platform-agnostic, API-first content infrastructure that&#8217;s optimized for AI discoverability, while maintaining the accuracy and accountability that government requires.</p>
<h2>3. The &#8220;Fans First&#8221; Philosophy: Eliminating Friction in Government Services</h2>
<p>Keynote speaker Jesse Cole of the Savannah Bananas brought his &#8220;Fans First&#8221; philosophy to the symposium, emphasizing that every moment of friction, from sign-up to service, is an opportunity for your audience to walk away. Sitecore&#8217;s product vision centers on eliminating these friction points to build trust and loyalty.</p>
<p>Government services have historically been synonymous with frustration: confusing forms, broken links during emergencies, information buried in PDFs, and websites that don&#8217;t work on mobile devices. But it doesn&#8217;t have to be this way.</p>
<p>The &#8220;Fans First&#8221; philosophy translates directly to &#8220;Constituents First&#8221; for government:</p>
<ul>
<li>Every additional click to find wildfire evacuation information is a potential life-safety issue.</li>
<li>Every confusing form reduces participation in critical benefit programs.</li>
<li>Every broken link during an emergency erodes trust in government.</li>
<li>Every accessibility barrier excludes vulnerable Californians who need services most.</li>
</ul>
<p>Our recent work with Cal FIRE and other state agencies exemplifies this principle. We unify fragmented information across multiple sites, enhance search functionality, incorporate engaging visuals, and optimize an interactive map relied upon by millions of users during critical events to eliminate friction in delivering government services.</p>
<h2>The SymSoft&#8217;s take</h2>
<p>The innovations unveiled at Sitecore Symposium 2025 extend far beyond marketing automation and content management. They represent a fundamental shift in how governments can engage and serve their constituents in a GenAI-first world.</p>
<p>At SymSoft, we’ve spent nearly two decades helping California’s public sector stay ahead of emerging technologies and evolving citizen needs. Today, we’re partnering with agencies such as <a href="https://www.symsoftsolutions.com/news-press-release/symsoft-solutions-powers-californias-genai-revolution-with-axyom-assist-at-cdtfa/">CDTFA</a>, <a href="https://www.symsoftsolutions.com/case-studies/california-department-of-forestry-and-fire-protection-website/">CAL FIRE,</a> and <a href="https://www.symsoftsolutions.com/case-studies/ai-assistant-dwr-intranet/">DWR</a> to deliver essential information through AI-powered summaries and voice assistants, extending service delivery far beyond the traditional website homepage.</p>
<p>Whether your agency is navigating a legacy CMS, planning a major digital modernization, or seeking to understand how Sitecore’s latest innovations can advance your mission, our team is ready to help.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Agile Project Management and Organizational Partnership in an Intranet Project</title>
		<link>https://www.symsoftsolutions.com/sitecore/agile-project-management-and-organizational-partnership-in-an-intranet-project/</link>
		
		<dc:creator><![CDATA[SymSoft Solutions]]></dc:creator>
		<pubDate>Thu, 18 Feb 2021 19:35:04 +0000</pubDate>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Digital Experience]]></category>
		<category><![CDATA[Employee Experience]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=8110</guid>

					<description><![CDATA[This article is the second part of our Department of Water Resources’ Intranet case study that Bianca Sievers, Kevin See, and Bhavik Patel presented at Sitecore Symposium 2020. In case you missed it, read the previous part about Intranet business opportunities and how to identify them. Kevin shares his perspective—and we further elaborate—on: Forming partnerships [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>This article is the second part of our Department of Water Resources’ Intranet case study that Bianca Sievers, Kevin See, and Bhavik Patel presented at Sitecore Symposium 2020. In case you missed it, read the previous part about <a href="https://www.symsoftsolutions.com/sitecore/intranet-business-opportunities-and-how-to-identify-them/">Intranet business opportunities and how to identify them</a>.</p>



<p>Kevin shares his perspective—and we further elaborate—on:</p>



<ol class="wp-block-list"><li><a href="#forming-partnerships" class="rank-math-link">Forming partnerships up, down, and across the organization.</a></li><li><a href="#intranet-vendor" class="rank-math-link">How to select the right vendor partner for the intranet project?</a></li><li><a href="#accelerate-timeline" class="rank-math-link">How to deliver a project in 90 days by accelerating the project timeline?</a></li><li><a href="#rapid-prototyping" class="rank-math-link">How can rapid prototyping be incorporated into a time-constrained project?</a></li></ol>



<p>Watch the video starting at about 3 minutes in, or skip to specific parts using the links above.</p>



<p></p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Building an Engaging Intranet with Sitecore" width="1080" height="608" src="https://www.youtube.com/embed/-keK_3WQd8Y?start=174&#038;feature=oembed"  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>DWR’s intranet project was successful in large part because of the stakeholders’ attention and the team’s dedication. To deliver the project in such a short timeframe (90 days), we needed to form strong partnerships:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p><strong><em>Kevin See:</em></strong><em> Now, here comes the fun part. How did we do it? We had to form partnerships — the partnership with the business, the partnership with technology, and of course, our vendor partnership. The first really big piece is — our director was in full support of this initiative, but we also had executive sponsorship from our deputy director of business operations, which runs the horizontal business. So everything from HR to IT is run under business operations.</em></p><p><em>The next part is the partnership between the director’s office, where Bianca is at, and the technology office [Kevin’s office]. Bianca represents the policy, the content, and the features people want. I represent the technology in terms of how we did it.</em></p><p><em>The last very important piece is that partner engagement. We had to find a partner that met the speed we wanted to go with, that also shared the same values, vision, and goals that we wanted to share. And have the flexibility to dynamically shift where we needed to to get the job done. And that was really [the case] with our SymSoft partner and working with Bhavik.</em></p></blockquote>



<p><em>[The transcript was edited for clarity and brevity from the original audio recording. References to the slides were removed from the transcript.]</em></p>



<h2 class="wp-block-heading" id="forming-partnerships"><strong>Forming partnerships up, down, and across the organization is crucial for the success of an intranet project.</strong></h2>



<p>In a typical project, vertical communication between supervisors and their reports is a natural extension of a regular reporting routine. Many times though, that same routine and reporting frameworks can steal attention from the project at hand, because other things may take priority or urgency, and meetings may be repurposed for other pressing topics. Also, while it makes perfect sense to include stakeholders from across different divisions and offices, oftentimes their attention is elsewhere, and their calendars are difficult to coordinate.&nbsp;&nbsp;</p>



<p>In short, partnerships require dedication, structure, and excitement, which is in many cases much easier to accomplish if the team is nimble and focused and the communication is direct and candid, instead of managed and indirect.</p>



<p>Not everyone has the opportunity to form small teams as we had at the DWR’s project. This is why in large organizations, we often suggest inviting divisional representatives with decision-making power delegated by the division’s head. And especially if the division executives are stretched too thin by directly participating in the project. A useful model for defining stakeholder roles and responsibilities is the <a href="https://www.cio.com/article/2395825/project-management-how-to-design-a-successful-raci-project-plan.html" target="_blank" rel="noopener">RACI matrix</a>, which describes who is Responsible, Accountable, Consulted, and Informed.</p>



<p>To secure resources and bandwidth across divisions get executive support with a clear vision for the project’s success. Equip your leadership with talking points and clear engagement requirements, so that they can relay the message with better clarity about the timelines, efforts, expectations, and specific action items. It’s much easier for divisions to commit resources when expectations are clear.</p>



<h2 class="wp-block-heading" id="intranet-vendor"><strong>How to select the right vendor partner for the intranet project?</strong></h2>



<p>To identify whether the vendor partnership will be successful, it’s useful to ask a few questions:</p>



<ol class="wp-block-list"><li><strong>What type(s) of vendor contributors are you going to collaborate with during the course of the project?</strong> Will you work with the experts directly, or will someone be a liaison between you and the expert? Are you looking for a vendor that can participate in strategic decisions, or are you looking at the production partner only? </li><li><strong>What is the team’s availability for the length of the project?</strong> Who is engaged at different stages of the project? What will the handover from discovery, to design, to development, to deployment look like? Is there any quality control to ensure a smooth transition between different stages of the project?</li><li><strong>What are some other functions inside the client organization that might contribute to the project?</strong> What will be their availability? Will we get reviews and approvals in a timely manner? How will the project team present work in progress to internal stakeholders and seek feedback?</li></ol>



<p>Asking these questions from the perspective of the project goal will help you realistically allocate internal resources, budget for external help, and set timeline expectations.&nbsp;</p>



<p>Now that we identified partnership considerations, let’s explore some practical tips and tricks that can help us accelerate project delivery.&nbsp;</p>



<h2 class="wp-block-heading" id="accelerate-timeline"><strong>How to deliver a project in 90 days by accelerating the project timeline?</strong></h2>



<p>Let’s start with Kevin’s insights from the intranet project:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p><strong><em>Kevin See:</em></strong><em> The “how” part is the agile delivery model. We had 90 days to get it done. Why 90 days? We had to get it done by Christmas time. That was our goal. Our time and our resources were tightly controlled. Our scope was to build an awesome and engaging intranet that employees love. It is very broad in scope in terms of what it’s going to be delivered.</em></p><p><em>Our time, as I mentioned, 90 days, got to get it done by Christmas time. Our resources? Well, that was our team. We had the resources that we had, and that was it. So we had to do all that within this very short and tight scope and build the intranet that people would use.</em></p><p><em>Decision- and policy-makers were a part of the product team. It wasn’t where we had a decision- and policy-makers that met once a month to talk about where the challenges are. The typical process in terms of how it goes is a steering committee. [But] they were actually a part of the team on a day-to-day basis. Bianca and I met literally every day or every other day. Between Bianca, Bhavik, and myself, we saw each other more than we saw our families within this 90-day timeframe. We shared a single vision, the vision of building the intranet that employees love, the vision of building the intranet within 90 days. And to get it done.</em></p></blockquote>



<h3 class="wp-block-heading"><strong>How did we apply agile delivery to the DWR’s intranet project?</strong></h3>



<p>To help us accelerate the project timeline, we used the agile delivery model and rapid prototyping (more about rapid prototyping below). We were able to utilize agile delivery because we met a couple of important essential ingredients:</p>



<ol class="wp-block-list"><li><strong>We worked as a small, fast team.</strong> While it is possible to apply agile delivery to a much bigger team of teams, it would require some preparation time to organize decentralized communication between smaller teams that follow the agile approach. We didn’t have the luxury to step back, so individual team members instead prioritized this project and focused on fully understanding the ins and outs in order to make informed decisions. By keeping the team small, we completely removed any overhead.</li></ol>



<ol class="wp-block-list" start="2"><li><strong>We communicated daily. </strong>Granted, daily communication wouldn’t be possible with a much larger team spread across multiple projects. The cost of task and project switching would be too high, and it would require additional effort to maintain the common vision and priorities.</li></ol>



<ol class="wp-block-list" start="3"><li><strong>We provided feedback instantly.</strong> When the team is focused on the project with little to no distractions, feedback and decisions are made on-the-fly and based on shared understanding and common knowledge of the project.</li></ol>



<ol class="wp-block-list" start="4"><li><strong>We made quick adjustments and shortened release cycles.</strong> Because the team was very intimate with the technical platform (Sitecore), it was possible for us to update and compile features and to try different options. This wouldn’t be possible without both content and platform owners’ expertise in content publishing on the Web.&nbsp;</li></ol>



<ol class="wp-block-list" start="5"><li><strong>We trusted one another.</strong> To develop trust, it is important to have a vision of the outcome that is attainable as well as assemble a team that shares that vision. A clear vision also helps with prioritizing features.</li></ol>



<ol class="wp-block-list" start="6"><li><strong>We prioritized features based on the project goals. </strong>As we were developing and implementing features, we developed a good sense of how much each addition or change would impact timelines and efforts. Instead of only focusing on development time, we also considered organizational policies and content governance. A good method for feature prioritization is the <a href="https://en.wikipedia.org/wiki/MoSCoW_method" target="_blank" rel="noopener">MoSCoW analysis</a> that identifies Must-have, Should-have, Could-have, and Will-not-have features.</li></ol>



<p>If your organization hasn’t already adopted an agile methodology, we suggest trying it with a small team that can operate within the framework described above. It is also useful to start implementing agile in your organization by following the <a href="http://agilemanifesto.org/" target="_blank" rel="noopener">agile manifesto</a>:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p><em>Individuals and interactions over processes and tools</em>.</p><p><em>Working software over comprehensive documentation</em>.</p><p><em>Customer collaboration over contract negotiation</em>.</p><p><em>Responding to change over following a plan</em>.</p></blockquote>



<h3 class="wp-block-heading"><strong>How to prepare for a tight deadline project?</strong></h3>



<p>Even if you don’t follow agile methodology, or are not sure if you’d end up applying it, any project can move quickly and meet deadlines with some basic preparation:</p>



<ol class="wp-block-list"><li>Commit to the minimum projects requirements.</li><li>Define project goals and success criteria.</li><li>Secure executive sponsorship.</li><li>Book important meetings far in advance.</li></ol>



<h3 class="wp-block-heading"><strong>How to keep the project moving?</strong></h3>



<p>There are also a number of simple practices teams can implement and stick to in order to keep making good progress and avoid pitfalls:</p>



<ol class="wp-block-list"><li><strong>Appoint a project manager</strong> who will attend all meetings, track decisions, and serve as an information hub. Best results are accomplished when they work closely with the vendor’s project manager.</li></ol>



<ol class="wp-block-list" start="2"><li><strong>Show something tangible early.</strong> It’s much more cost-effective to course-correct a proof of concept or a prototype than a fully developed project. Depending on the fidelity level, and stakeholder experience, it’s a good idea to present progress in a broader context of project requirements.</li></ol>



<ol class="wp-block-list" start="3"><li><strong>Keep key decision-makers in the loop</strong> by presenting small changes often. This will make it easy for them to recall the previous decisions and ask questions early, rather than approving a major milestone without enough context.</li></ol>



<ol class="wp-block-list" start="4"><li><strong>Contain the scope</strong> by always going back to the minimum project requirements. Any additional ideas and opportunities should be moved to the backlog and revised after the must-have features are designed, implemented, and tested.</li></ol>



<h2 class="wp-block-heading" id="rapid-prototyping"><strong>How can rapid prototyping be incorporated into a time-constrained project?</strong></h2>



<p>DWR’s team is a huge fan of rapid prototyping, especially since they were deeply invested in the project and excited about the possibilities. </p>



<p>The line between rapid prototyping and agile methodology is sometimes blurry. Rapid prototyping focuses on the software design from the user and business stakeholder perspective, while agile methodology applies to software development. The confusion stems from the fact that both are iterative methodologies with short release cycles, and both can be performed in the software environment. Still, it’s important to remember that prototypes are not production-ready.&nbsp;</p>



<p>For example, before committing to a full-blown web form that connects to various systems and databases, you might embed a <a href="https://www.google.com/forms/" target="_blank" rel="noopener">Google Form</a> into a page to validate the user flow. Or, before committing to a custom developed data-dashboard, you might embed a <a href="https://www.tableau.com/" target="_blank" rel="noopener">Tableau</a> prototype as an iframe. Yet another example is prototyping a widget without actually connecting it to the database. None of these examples would be shipped to production, but would give everyone a good idea of whether the feature makes sense to develop further or not.</p>



<p>Compared to the waterfall approach, which includes detailed planning and rigid requirements <em>outside</em> of the development environment, rapid prototyping enables quick validation of scaled features and provides a short feedback loop. In short, rapid prototyping boosts decision-making processes, dramatically reducing refactoring in the actual development phase.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p><strong><em>Kevin See: </em></strong><em>We’ve done a lot of things in terms of rapid prototyping, meaning: what we saw in the morning could be dramatically different by the evening time. It can be 180 degrees. “You know what? That feature worked. [Or] it didn’t work.” What was the benefit behind that? We might have lost a couple of hours. In a typical development timeframe, a feature might take weeks or months to get done, and you lost all that time. But we worked with a partner, with a business that really was aligned with what we were trying to do, and that is to get the job done, and course-correct and shift, as fast as we want to shift and course-correct.</em></p><p><em>I think this was pivotal in terms of getting the platform that can do that, finding a partner that’s willing to do that with you, and a business that is truly engaged and is a part of that process. “Yep, that didn’t work. Let’s move on. Yep, that worked. Let’s move on.” And I think this is key in how we got this thing done within this very tight and short timeframe of building the Department of Water Resources’ intranet.</em></p></blockquote>



<p>As previously mentioned, rapid prototyping goes hand in hand with the agile methodology, because it streamlines quick adjustments and shortened release cycles. However, it is the most suitable for experienced teams who can make such quick changes, validate options with stakeholders, and make informed decisions. This can also be a disadvantage, since rapid prototyping requires the most knowledgeable and experienced personnel.</p>



<p>Lastly, rapid prototyping is also effective in MVP (minimum viable product) development, where the PoC (proof of concept) is more important than a specific implementation approach. When the timeline is short, rapid prototyping results in a tangible output very early. Once approved, the MVP can be moved into the development phase.</p>



<h2 class="wp-block-heading"><strong>Conclusion</strong></h2>



<p>While large-scale capital projects can be delivered in a very short timeframe, they require an experienced team, executive support, and dedicated stakeholders. By applying methodologies and frameworks, such as RACI stakeholder roles, MoSCoW prioritization, agile project management, and rapid prototyping, even the most challenging projects can be delivered on time and budget.</p>



<p>Have a massive project that needs to be delivered fast? <a href="https://www.symsoftsolutions.com/contact/">Contact us and let’s start the conversation</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What to Consider When Planning a Government Website Redesign</title>
		<link>https://www.symsoftsolutions.com/sitecore/what-to-consider-when-planning-a-government-website-redesign/</link>
		
		<dc:creator><![CDATA[Daniel Calzada]]></dc:creator>
		<pubDate>Thu, 11 Feb 2021 21:35:58 +0000</pubDate>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Digital Experience]]></category>
		<category><![CDATA[Web Design]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=8075</guid>

					<description><![CDATA[Incorporating relevant tasks and deliverables when planning a website redesign or implementation project will significantly impact the overall project approach and outcomes. While identifying most of the features, requirements, and deliverables is a straight-forward process, there are a few critical activities that can be easily missed in the early stages of project planning.]]></description>
										<content:encoded><![CDATA[
<p>Incorporating relevant tasks and deliverables when planning a website redesign or implementation project will significantly impact the overall project approach and outcomes. While identifying most of the features, requirements, and deliverables is a straight-forward process, there are a few critical activities that can be easily missed in the early stages of project planning.</p>



<p>In over 15 years of redesigning websites and implementing Web content management systems for our enterprise and government clients, we have identified five essential activities that are often missed in the project planning. In such cases, the whole project might be at risk because time and internal resources are not allocated. Of course, when this happens, there are still ways to deliver a project, but it might require readjustment that could have been easily avoided altogether.</p>



<p>Before you plan for your next Web design or <a href="https://www.symsoftsolutions.com/content-management-systems/" class="rank-math-link">Web CMS implementation</a> project, we suggest you consider the following five activities of a successful redesign:</p>



<ol class="wp-block-list"><li><a href="#content-production-editing-and-migration" class="rank-math-link">Content Production, Editing, and Migration</a></li><li><a href="#web-content-accessibility-support" class="rank-math-link">Web Content Accessibility Support</a></li><li><a href="#application-and-system-integration" class="rank-math-link">Application and System Integration</a></li><li><a href="#organizational-change-management" class="rank-math-link">Organizational Change Management (OCM)</a></li><li><a href="#maintenance-and-support" class="rank-math-link">Maintenance and Support</a></li></ol>



<h2 class="wp-block-heading" id="content-production-editing-and-migration"><strong>1. Content Production, Editing, and Migration</strong></h2>



<p>Whether you are redesigning a site or launching a completely new website, content migration and new content production are critical activities that require careful planning and consideration.&nbsp;</p>



<p><a href="https://www.symsoftsolutions.com/content-services/" class="rank-math-link">Content updates and organization</a> typically require engagement of the content owners and subject matter experts, such as program managers or communication teams. Failure to plan for their involvement results in low engagement and unanticipated workloads that nobody allocated for. It is common for organizations at that point to step back and re-identify project stakeholders, which in many cases results in inconvenience and delays.</p>



<p>To avoid surprises down the road, ask the following questions:</p>



<ol class="wp-block-list"><li>How much content is currently there on the existing website?</li><li>Will all the current content be migrated to the new website?</li><li>Can content be archived?</li><li>Does some content belong to the Intranet or Extranet rather than the public-facing website?</li><li>What is the legally required content that needs to be migrated over to the new website?</li><li>Do you need to create any new content, or update any existing content for the new website?</li><li>Will you introduce new content formats, such as photography, illustrations, or video?</li><li>Who will produce or edit content?</li><li>Who will migrate the content?</li><li>Who will review and approve content editing and migration?&nbsp;</li></ol>



<p>Answering these questions prior to starting the project will help you define a more realistic scope, and identify additional resources needed to ensure the delivery of a comprehensive website solution.</p>



<h2 class="wp-block-heading" id="web-content-accessibility-support"><strong>2. Web Content Accessibility Support</strong></h2>



<p>Accessible websites combine accessibility compliant platforms (e.g. content management systems or document filing systems) and accessibility compliant content.</p>



<p>While most public sector website redesign or implementation projects require an accessibility compliant platform, software, and design system, content accessibility compliance workflows and procedures are often overlooked. This can create challenges after the project is completed and the website content continues to evolve, so it is essential to establish and adopt processes to <a href="https://www.symsoftsolutions.com/accessibility-compliance/" class="rank-math-link">monitor and ensure accessibility compliance</a> moving forward.</p>



<p>When planning your next accessibility compliant project, ask the following questions:</p>



<ol class="wp-block-list"><li>How will you test and validate website accessibility after the project is completed? How will you keep the website accessible? This is especially important in public sector websites that need to self-certify for accessibility compliance (<a href="https://www.symsoftsolutions.com/accessibility-compliance/becoming-ab434-compliant-a-step-by-step-guide/" class="rank-math-link">AB 434 in California</a>).</li><li>Are there any files and documents that need to be remediated for accessibility compliance before publishing on the website? (In many cases the answer is yes.) How many of such documents are already remediated? Do you have a strategy set in place to conduct remediation of the non-compliant files and documents? In our experience, the volume of documents that require at least some accessibility remediation comes as a surprise to many organizations.</li><li>Do you have the technical resources and expertise to maintain an accessibility compliant website? If not, how do you plan to address the gap?</li></ol>



<h2 class="wp-block-heading" id="application-and-system-integration"><strong>3. Application and System Integration</strong></h2>



<p>Many organizations, especially in the public sector, provide website visitors access to <a href="https://www.symsoftsolutions.com/enterprise-mobile-applications/" class="rank-math-link">business applications</a> through their websites. These applications help with self-service tasks and therefore significantly optimize business processes, digital transactions, and time required to serve thousands and millions of users. Such applications are often the main reason users visit the website, so consider business application integration while planning for a website redesign or implementation project.</p>



<p>To help identify tasks and resources that should be part of your project, review all applications currently available to the users through the website. Consider engaging the business application owners and technical support groups in the planning.&nbsp;&nbsp;</p>



<p>In our experience, there are a few common scenarios:</p>



<ol class="wp-block-list"><li><strong>Business applications are kept as-is. </strong>They retain their look-and-feel and are hosted in the existing environment. Applications are not integrated with the main website but are merely hyperlinked. In this case, the user experience and accessibility could end up being suboptimal, but the project timelines are more predictable.</li><li><strong>Existing application rebranding and visual design alignment.</strong> This is a common option for organizations that are able to dedicate technical staff who can apply the main project’s design system to the business application.</li><li><strong>API development and integration.</strong> This is the most future-proof solution, depending on the CMS and how much development effort is required by the complexity of the business application. Benefits of API integrations include a unified brand and user experience because the user stays within the same website, which opens up possibilities for additional features such as content personalization or user profile functionalities.</li></ol>



<p>Sometimes, the rebranded applications are embedded through iframes. However, we strongly suggest avoiding this approach as it may create accessibility challenges that are expensive to address. Typically, video embeds are somewhat easier to maintain, but custom data dashboards might create more problems than benefits when embedded through an iframe.</p>



<p>As always, there are multiple solutions to a problem, but we recommend at least high-level planning, well in advance, to avoid surprises later in the process.</p>



<h2 class="wp-block-heading" id="organizational-change-management"><strong>4. Organizational Change Management (OCM)</strong></h2>



<p>Implementing new systems and tools may require changes to the organization’s internal processes, procedures, and day-to-day operations. Planning and managing the change is sometimes omitted from the project planning process, resulting in low stakeholder engagement and slow adoption.&nbsp;&nbsp;</p>



<p>When planning the project, changes and challenges that need to be identified include:</p>



<ol class="wp-block-list"><li>Changes in roles and responsibilities.&nbsp;&nbsp;</li><li>Implementation of new processes, policies, and procedures.</li><li>New resources, skills, or abilities required within the organization.</li><li>Legal requirements for implementing the changes.</li><li>Impact of the changes on the organization’s workload.&nbsp;&nbsp;</li></ol>



<p>We have partnered with many of our clients to help lead organizational change management throughout our projects, which has been vital for successful implementations and enduring solutions.</p>



<h2 class="wp-block-heading" id="maintenance-and-support"><strong>5. Maintenance and Support</strong></h2>



<p>Although most website redesign or implementation projects include a knowledge transfer deliverable, some miss the option of engaging the implementing partner to provide <a href="https://www.symsoftsolutions.com/cloud-devops/" class="rank-math-link">ongoing maintenance and support</a> after the project is complete.</p>



<p>Having maintenance and support in place allows organizations to gain additional knowledge of the solutions by monitoring issue resolution procedures, collaborating with the vendor to resolve real-life situations, and learning by doing. Having maintenance and support in place frees up internal resources to focus on more strategic tasks than day-to-day monitoring.</p>



<p>When planning the project, thinking about the organizational capabilities will provide you with a general idea of the maintenance and support requirements that should be included in the project&#8217;s scope. Consider:</p>



<ol class="wp-block-list"><li>Your organization’s familiarity with the platforms and technologies used in the project.</li><li>What resources will be available to support the solution after the new website is launched.&nbsp;&nbsp;</li></ol>



<h2 class="wp-block-heading"><strong>Conclusion</strong></h2>



<p>We hope this list of considerations will give you a better idea on how to scope website redesign or Web CMS implementation projects in your organization.</p>



<p>For further questions, and help in scoping projects, please <a href="/contact/" class="rank-math-link">contact us</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Sort Sitecore Solr Filters in Alphabetical Order</title>
		<link>https://www.symsoftsolutions.com/sitecore/how-to-sort-sitecore-solr-filters-in-alphabetical-order/</link>
		
		<dc:creator><![CDATA[Xing Liu]]></dc:creator>
		<pubDate>Fri, 29 Jan 2021 02:04:17 +0000</pubDate>
				<category><![CDATA[Sitecore]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=7899</guid>

					<description><![CDATA[Sitecore Solr provides an abundance of advanced search features, but even without implementing anything as advanced as stemming, or search term suggestions, Solr’s default algorithm provides excellent relevancy in the search results. We’ve implemented Sitecore Solr in a number of complex projects like the student-centered website for California Community Colleges, the Department of Water Resources [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Sitecore Solr provides an abundance of <a href="https://www.symsoftsolutions.com/sitecore/advanced-search-experience-with-sitecore-and-solr/" class="rank-math-link">advanced search features</a>, but even without implementing anything as advanced as stemming, or search term suggestions, Solr’s default algorithm provides excellent relevancy in the search results. We’ve implemented Sitecore Solr in a number of complex projects like the <a href="https://www.symsoftsolutions.com/sitecore/california-community-colleges-chancellors-office/" class="rank-math-link">student-centered website for California Community Colleges</a>, the <a href="https://www.symsoftsolutions.com/sitecore/california-department-of-water-resources-website-redesign/" class="rank-math-link">Department of Water Resources website</a> and <a href="https://www.symsoftsolutions.com/sitecore/blue-dwr-intranet/" class="rank-math-link">Intranet</a>, and the <a href="https://www.symsoftsolutions.com/sitecore/california-department-of-general-services/" class="rank-math-link">multi-organizational Department of General Services</a>. </p>



<p>Alphabetical listing of items such as navigation items or search filters is one of the easiest ways for people to navigate and find what they are looking for in a long list of terms.</p>



<h2 class="wp-block-heading"><strong>However, the search filters returned from Solr are not sorted alphabetically.</strong></h2>



<p>Instead of the natural language terms, Solr returns a list of facet IDs in the order that Solr internally determined based on relevancy. </p>



<p>Below is an example of the Solr Search data structure, which makes sense to the algorithm, but not necessarily to the website visitors that use search filters.</p>



<pre class="wp-block-preformatted">[0]: "9955d3531ccb4e6e8a92c7e484d329ca"
[1]: "dac1e325382d48569cabea48c83165cd"
[2]: "e56edf635d4048a098bcbeaef8541975"
[3]: "ef1770d934f54b6b821d29be800667b9"</pre>



<p>Looking at the example above, items are represented as Sitecore GUIDs. Applying an ascending order operation to the list above won’t make sense, because at this point we don’t know what’s the actual user-friendly label associated with each ID. </p>



<h2 class="wp-block-heading"><strong>To apply meaningful sorting to Solr search results, we have to do a little bit of preparation.</strong></h2>



<ol class="wp-block-list" type="1"><li>Make a new list.</li><li>Translate each ID into the corresponding Sitecore Item and add it to the newly created list.</li><li>Find out each item’s associated title.</li><li>Sort the new list based on the associated title.</li></ol>



<p>Translated to the code language, it looks like the example below:</p>



<pre class="wp-block-preformatted">ret = asc ? ret.OrderBy(x =&gt; x["Title"]).ToList() : ret.OrderByDescending(x =&gt; x["Title"]).ToList();
List ret = new List();
foreach (var filter in allFilters) {
    Item filterItem = Sitecore.Context.Database.GetItem(new Sitecore.Data.ID(filter));
    ret.Add(filterItem);
}</pre>



<p>I hope this helps you sort the returned facets. For a live example, please visit <a href="https://www.cccco.edu/Search-Memos-and-Official-Documents" class="rank-math-link" target="_blank" rel="noopener">CCC’s Custom Document Search</a>. </p>



<p>As always, feel free to <a href="https://www.symsoftsolutions.com/contact/" class="rank-math-link">reach out to us with feedback and further questions</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Intranet Business Opportunities and How to Identify Them</title>
		<link>https://www.symsoftsolutions.com/sitecore/intranet-business-opportunities-and-how-to-identify-them/</link>
		
		<dc:creator><![CDATA[SymSoft Solutions]]></dc:creator>
		<pubDate>Wed, 27 Jan 2021 22:53:58 +0000</pubDate>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Digital Experience]]></category>
		<category><![CDATA[Employee Experience]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=7843</guid>

					<description><![CDATA[Design systems have emerged as a popular tool for organizations in recent years because of their ability to support business goals and communicate brand values by providing a unified and consistent design language to work with. With this integrated set of tools and guidelines, organizations are able to effectively utilize design across the entire product line, making decisions easier, saving more time, and optimizing the end-user experience. ]]></description>
										<content:encoded><![CDATA[
<p>Organizations and businesses in recent years have sought ways to increase the productivity of their workforces, and eliminate barriers to communication. One way of doing so has been implementation of <strong>intranets</strong>. These private computer networks have the look and feel of public websites or social media feeds, allowing for seamless communication, collaboration, and sharing of resources.</p>



<p>Some organizations have not adopted intranet platforms, instead opting to rely on a variety of other solutions, such as email and third-party messenger systems. Others have implemented intranets which, after years or decades of growth and changes in organizational scope and scale, no longer meet their present-day goals and vision.</p>



<p>Whether you have an existing intranet or not, there are common problems that can indicate that a modern intranet system is necessary for your continued success.</p>



<h2 class="wp-block-heading">Organizations sometimes reach a halt where the necessary scope of a new intranet system is daunting, but the ability to grow and improve their level of service requires attacking the problem.</h2>



<p>In early 2019, we were approached by the California Department of Water Resources. The scope of the DWR is <em>immense</em>. They are responsible for supplying water to 27 million Californians and 750,000 acres of agricultural land, and also provide oversight for more than a dozen dams in the state of California. These responsibilities require a large, diverse workforce: the DWR is composed of approximately 3,500 employees across 14 offices in various urban and rural locations.</p>



<p>As you can imagine, any and every hindrance to communication was keenly felt. They knew their needs had outstripped their existing internal communication infrastructure. But it takes a significant, committed effort to shift focus from short-term, day-to-day priorities, and taking a step back and seeing the big picture.</p>



<p>To their credit, DWR recognized they had hit a point where they couldn’t hide from the challenge any longer, and had to get all relevant stakeholders involved: execs, operations, IT, communications, HR and legal, and of course, their base level employees.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Building an Engaging Intranet with Sitecore" width="1080" height="608" src="https://www.youtube.com/embed/-keK_3WQd8Y?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div><figcaption>In the video presentation “Building an Engaging Intranet with Sitecore” prepared for the Sitecore Symposium 2020, DWR’s Bianca Sievers and Kevin See, and SymSoft’s Bhavik Patel share their experience and anecdotes about the project requirements, organizational support, executing on the vision, and project outcomes.</figcaption></figure>



<h2 class="wp-block-heading">An inadequate intranet often results in the loss or misplacement of institutional information, failures in communication between executives and employees, and ongoing difficulties for the rank-and-file.</h2>



<p>The difficulties that arise from aging, insufficient intranet are often felt both at the organizational level, and at the personal level.</p>



<p><strong>Problems that arise at the macro scale can include:</strong></p>



<ul class="wp-block-list"><li><strong>Loss of documentation</strong>. Documents—both archival and current—can become difficult to find, as employees come and go and filing systems shift and change over time. It can become necessary to conduct weeks- or months-long content audits to identify what documents exist, and where.</li><li><strong>Disjointed communication</strong>. As with document archives, an inadequate intranet system results in the fragmentation of every aspect of communication. Knowledge is lost, performance metrics are opaque, and efficiency is compromised. The result is an incoherent execution of an organization’s vision, mission, and values.</li><li><strong>Social isolation</strong>. As a result of poor communication, workers often feel isolated, cut off from others by the four walls around them. They have no way of seeing the larger picture, and no way to appreciate the positive impact of their work. Work often comes to feel repetitive and unfulfilling at all levels.</li><li><strong>Lack of community and mission</strong>. Public social media platforms are appealing for a reason—they give a sense of community and connection. Failure to provide for the social needs of the workforce results in an organization that has no central identity, with mission statements that carry little or no real-world weight. Organizational plans, milestones, and updates are not shared, never making it out the door of the boardroom.</li></ul>



<p>Shortcomings in intranet sophistication are also evident to the rank-and-file. <strong>Common employee-level issues include:</strong></p>



<ul class="wp-block-list"><li><strong>Intranet as info dump</strong>. A lackluster intranet often becomes nothing more than a bucket for informational storage. In these instances, file search and navigation features are inadequate. This means that documents, manuals, and guidelines are difficult or impossible to find, and multiple, conflicting versions are generated over time.</li><li><strong>Distribution outside the intranet</strong>. In these situations, the sharing of information often occurs outside of the intranet, with employees instead relying on email, and third-party messengers like Teams and Slack. Consequently, not everyone has the same information, or even the ability to access the same information.</li><li><strong>Improper data storage</strong>. Because of distribution occurring outside the intranet, files are often archived as email attachments or in user drives, rather than in common storage.</li><li><strong>Success not communicated</strong>. With an intranet not being an effective means of communication, personnel successes are never communicated.</li></ul>



<p>But the most obvious symptom of an inadequate intranet is that it delivers an experience that is subpar to Internet services and third-party communication tools, so that it becomes the option of last resort.</p>



<h2 class="wp-block-heading">But these are problems that can be resolved by making a comprehensive, top-to-bottom commitment to developing an intranet that betters your entire organization.</h2>



<p>To return to the challenge facing our client, DWR, they recognized that their existing intranet did not serve the needs of their employees. A platform was needed that was flexible enough to accommodate the unique needs of each employee, as well as a unified connection and understanding of key needs and goals.</p>



<p>In the summer of 2019, we brought together over a hundred and twenty employees to participate in focus groups for the intranet redesign. These participants were specifically selected to better understand the diverse needs within the workforce, based on their skills, geography, and position within the network. Employees were asked to provide feedback on knowledge search information operation and networking. Our team listened and learned from DWR’s employees. And then, we prioritized those needs moving forward.</p>



<p>It was a significant challenge. But we succeeded because we led off by asking a handful of critical questions:</p>



<ul class="wp-block-list"><li>If you could wave a magic wand, what are the three things you would fix immediately?</li><li>What are you doing right now to address organizational challenges? What has worked, and what hasn’t?</li><li>What are the long-term goals of the organization?</li><li>How would the success of the project be measured?</li></ul>



<p>In the future, we will address how we develop a successful intranet system that meets the needs of an organization’s mission, as well as its rank-and-file staff. But every successful intranet project addresses three key needs:</p>



<ul class="wp-block-list"><li><strong>Accountability</strong>. At the outset, personnel are identified as being responsible for the successful execution of the project, so that the organization’s mission, values, and vision are sustained.</li><li><strong>Curation</strong>. Any successful intranet requires ongoing information curation, to ensure consistency in organization. There must be dedicated resources in place which will edit content, optimize, review, archive outdated content, track intranet performance, talk to employees, and conduct regular (often light weight) UX studies.</li><li><strong>Adoption</strong>. An intranet is not a project that, once it is completed, it is placed on a shelf. It is an operational asset. Plans must be put in place for how the organization will transition from the old intranet system, to the newly developed one. All stakeholders must commit to making this transition. Otherwise, the organization will be in limbo between the legacy system, and the new one.</li></ul>



<p>In future posts, we will address other key topics in the development and launch of successful intranet systems. In the meantime, enjoy the video presentation we delivered at Sitecore Symposium and <a href="/contact/" class="rank-math-link"><strong>contact us with specific inquiries about your intranet project</strong></a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Sitecore error &#8220;Attempted to load invalid xml&#8221; or &#8220;ERROR First 200 characters: &gt;&#8221;</title>
		<link>https://www.symsoftsolutions.com/sitecore/sitecore-error-attempted-to-load-invalid-xml-or-error-first-200-characters/</link>
		
		<dc:creator><![CDATA[Susmitha Gutha]]></dc:creator>
		<pubDate>Fri, 17 Jan 2020 21:57:41 +0000</pubDate>
				<category><![CDATA[Sitecore]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=4415</guid>

					<description><![CDATA[When we were migrating from Sitecore 8.2 to 9.1.1 we found the following exception in our AppInsights Logs. Also, non-admin users were reporting that they would receive a fatal error that looks like the following: We weren&#8217;t sure what was happening but in the logs, we saw that it was being triggered during Item Locking [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>When we were migrating from Sitecore 8.2 to 9.1.1 we found the following exception in our AppInsights Logs.<br />
Also, non-admin users were reporting that they would receive a fatal error that looks like the following:</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-4421" src="https://www.symsoftsolutions.com/wp-content/uploads/2020/01/Error.png" alt="" width="385" height="346" /></p>
<p>We weren&#8217;t sure what was happening but in the logs, we saw that it was being triggered during <strong>Item Locking</strong> and <strong>Indexing</strong>.<br />
After some research, it was apparent that this was being caused by invalid XML in the lock field. Which looks like this</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-4417" src="https://www.symsoftsolutions.com/wp-content/uploads/2020/01/Lock-field.png" alt="" width="509" height="389" /></p>
<h5><strong>This issue can appear in the Sitecore logs in the following ways:<br />
</strong></h5>
<p>Error 1:<br />
<code>416 16:06:36 ERROR First 200 characters: &gt;</code></p>
<p>Error 2:<br />
<code>416 16:06:36 ERROR Call stack: at Sitecore.MainUtil.GetCallStack() at Sitecore.Xml.XmlUtil.LoadXml(String xml) at Sitecore.Data.Locking.ItemLocking.GetLockField() at Sitecore.Data.Locking.ItemLocking.GetOwner() at Sitecore.ContentSearch.ComputedFields.ParsedLockOwner.ComputeFieldValue(IIndexable indexable) at Sitecore.ContentSearch.AbstractDocumentBuilder`1.&lt;&gt;c__DisplayClass57_0.&lt;AddComputedIndexFieldsInParallel&gt;b__0(IComputedIndexField computedIndexField, ParallelLoopState parallelLoopState) at System.Threading.Tasks.Parallel.&lt;&gt;c__DisplayClass42_0`2.&lt;PartitionerForEachWorker&gt;b__1() at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask) at System.Threading.Tasks.Task.&lt;&gt;c__DisplayClass176_0.&lt;ExecuteSelfReplicating&gt;b__0(Object ) at System.Threading.Tasks.Task.Execute() at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task&amp; currentTaskSlot) at System.Threading.Tasks.Task.ExecuteEntry(Boolean bPreventDoubleExecution) at System.Threading.ThreadPoolWorkQueue.Dispatch()</code></p>
<p>Error 3:<br />
<code>10144 16:06:36 ERROR Attempted to load invalid xml. Exception: System.Xml.XmlException Message: Data at the root level is invalid. Line 1, position 1. Source: System.Xml at System.Xml.XmlTextReaderImpl.Throw(Exception e) at System.Xml.XmlTextReaderImpl.ParseRootLevelWhitespace() at System.Xml.XmlTextReaderImpl.ParseDocumentContent() at System.Xml.XmlLoader.Load(XmlDocument doc, XmlReader reader, Boolean preserveWhitespace) at System.Xml.XmlDocument.Load(XmlReader reader) at System.Xml.XmlDocument.LoadXml(String xml) at Sitecore.Xml.XmlUtil.LoadXml(String xml)</code></p>
<p><strong>Solution:<br />
</strong>We knew that we needed to find out how many and which Sitecore Items had this issue so that we could go and fix them through the Content Editor.  We decided that SQL was out best shot!</p>
<p>Run the following query in your Master database. The query returns the list of Items that have Invalid XML in the __Lock Field</p>
<p><code>SELECT TOP (1000) [Id]<br />
,[ItemId]<br />
,(select Name from Items where FieldId = ID) as FieldName<br />
,[Value]<br />
,[Created]<br />
,[Updated]<br />
FROM [Fields]<br />
where [Value] = '&gt;' or [Value] = '&lt;'</code></p>
<p>In my case, it returned 1 record in the master database for the __lock field.<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-4418" src="https://www.symsoftsolutions.com/wp-content/uploads/2020/01/Broken-fields-Report.png" alt="" width="1203" height="650" /></p>
<p>I then use the content editor and searched for the Item that was affected, and cleared out the lock field, as an admin of course! One its cleared out make sure you save and publish.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-4417" src="https://www.symsoftsolutions.com/wp-content/uploads/2020/01/Lock-field.png" alt="" width="509" height="389" /></p>
<p>If you are still receiving the error after clearing the fields, execute the same query on the VersionedFields and the SharedFields Table:</p>
<p><code>SELECT TOP 100 ItemId,(select Name from Items where FieldId = ID) as FieldName, LEN([Value]) as 'Length'<br />
FROM [VersionedFields]<br />
where ([Value] like '&lt;%' or [Value] like '&lt;' or [Value] like '%&lt;')<br />
Order by [Length]</code></p>
<p><code>SELECT TOP 100 ItemId,(select Name from Items where FieldId = ID) as FieldName, LEN([Value]) as 'Length'<br />
FROM [SharedFields]<br />
where ([Value] like '&lt;%' or [Value] like '&lt;' or [Value] like '%&lt;')<br />
Order by [Length]</code></p>
<p>Hopefully, this helps!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Update Contact using FXM javascript API</title>
		<link>https://www.symsoftsolutions.com/sitecore/update-contact-using-fxm-javascript-api/</link>
		
		<dc:creator><![CDATA[Pravin Suryavanshi]]></dc:creator>
		<pubDate>Wed, 08 Jan 2020 23:35:27 +0000</pubDate>
				<category><![CDATA[Sitecore]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=4381</guid>

					<description><![CDATA[Federated Experience Manager (FXM) application allows you to add Sitecore content on external non-Sitecore websites and track visitor interactions, generate analytics information as if it was a Sitecore site.]]></description>
										<content:encoded><![CDATA[<p>This blog demonstrates how to add or update Sitecore contact using FXM JavaScript API. Federated Experience Manager (FXM) application allows you to add Sitecore content on external non-Sitecore websites and track visitor interactions, generate analytics information as if it was a Sitecore site. It also allows us to leverage Sitecore personalization based on contact Identified. However, we had the following question &#8211; How can we identify the contact from the Non-Sitecore site using FXM, and then use the Sitecore Personalization engine to deliver targeted content?. This is what we came up with.</p>
<p>Sitecore FXM&nbsp;uses what they call a Beacon script to track and record the current users’ behavior (i.e interactions). Including this script will allow you to execute the following methods to track events, goals, outcomes, and campaigns. However, there are no available methods to identify a contact or update a contact&#8217;s facet data. This functionality is needed when we have a Non-Sitecore site using FXM that is also the application responsible for logging the user in, and then personalizing content based on a given attribute stored in xDb.</p>
<ol>
<li>SCBeacon.trackEvent</li>
<li>SCBeacon.trackGoal</li>
<li>SCBeacon.trackOutcome</li>
<li>SCBeacon.trackCampaign</li>
</ol>
<p>Looking at Sitecore 9.1 configs for FXM in Sitecore.FXM.config and Sitecore FXM assembly lead us to the TriggerEventsProcessor which is responsible for handling calls the Beacon method&#8217;s referrenced above.</p>
<pre><code>&lt;tracking.triggerpageevent&gt;

  &lt;processor type="Sitecore.FXM.Pipelines.Tracking.TriggerPageEvent.TriggerEventsProcessor, Sitecore.FXM" resolve="true" /&gt;

&lt;/tracking.triggerpageevent&gt;</code></pre>
<pre><code>public class TriggerEventsProcessor : ITriggerPageEventProcessor
  {
    private readonly IAnalyticsDefinitionsRepository _analyticsDefinitionsRepository;
    public TriggerEventsProcessor(IAnalyticsDefinitionsRepository analyticsDefinitionsRepository)
    {
      Assert.ArgumentNotNull((object) analyticsDefinitionsRepository, nameof (analyticsDefinitionsRepository));
      this._analyticsDefinitionsRepository = analyticsDefinitionsRepository;
    }
    public void Process(TriggerPageEventArgs args)
    {
      IPageContext currentPageContext = args.CurrentPageContext;
      Assert.IsNotNull((object) currentPageContext, "The current page is not tracked in the current session. No events can be triggered.");
      ITrackDescriptor trackDescriptor = args.TrackDescriptor;
      if (trackDescriptor is EventTrackDescriptor)
      {
        EventTrackDescriptor eventTrackDescriptor = (EventTrackDescriptor) trackDescriptor;
        this.TriggerPageEvent((IDefinition) eventTrackDescriptor.Definition, currentPageContext, eventTrackDescriptor.Data, eventTrackDescriptor.DataKey, eventTrackDescriptor.Extras);
      }
      else if (trackDescriptor is GoalTrackDescriptor)
      {
        GoalTrackDescriptor goalTrackDescriptor = (GoalTrackDescriptor) trackDescriptor;
        this.TriggerPageEvent((IDefinition) goalTrackDescriptor.Definition, currentPageContext, goalTrackDescriptor.Data, goalTrackDescriptor.DataKey, goalTrackDescriptor.Extras);
      }
      else if (trackDescriptor is CampaignTrackDescriptor)
      {
        CampaignTrackDescriptor campaignTrackDescriptor = (CampaignTrackDescriptor) trackDescriptor;
        currentPageContext.TriggerCampaign(campaignTrackDescriptor.Definition);
      }
      else if (trackDescriptor is OutcomeTrackDescriptor)
      {
        OutcomeTrackDescriptor outcomeTrackDescriptor = (OutcomeTrackDescriptor) trackDescriptor;
        OutcomeData outcome = new OutcomeData(outcomeTrackDescriptor.Definition, outcomeTrackDescriptor.CurrencyCode, outcomeTrackDescriptor.Monetary);
        IDictionary&lt;string, string&gt; extras = outcomeTrackDescriptor.Extras;
        if (extras != null &amp;&amp; extras.Count &gt; 0)
          outcome.CustomValues["FXM_CustomValues"] = (object) outcomeTrackDescriptor.Extras;
        currentPageContext.RegisterOutcome(outcome);
      }
      else
      {
        if (!(trackDescriptor is ElementMatcherTrackDescriptor))
          return;
        this.TriggerElement(((ElementMatcherTrackDescriptor) trackDescriptor).Item, currentPageContext);
      }
    }
  }</code></pre>
<p>Taking a look at the processor, SCBeacon.trackEvent does exactly what it says and tracks specific actions but does not handle any contact identifications or contact updates.</p>
<p>The next step is to create the custom process by extending (inheriting) the Sitecore default TriggerEventsProcessor with the following code:</p>
<pre><code>public class TriggerFXMEventsProcessor : Sitecore.FXM.Pipelines.Tracking.TriggerPageEvent.TriggerEventsProcessor
    {
        //private readonly IAnalyticsDefinitionsRepository _analyticsDefinitionsRepository;
        public TriggerFXMEventsProcessor(IAnalyticsDefinitionsRepository analyticsDefinitionsRepository) : base(analyticsDefinitionsRepository)
        {
        }
        public new void Process(TriggerPageEventArgs args)
        {
            IPageContext currentPageContext = args.CurrentPageContext;
            Assert.IsNotNull((object)currentPageContext, "The current page is not tracked in the current session. No events can be triggered.");
            ITrackDescriptor trackDescriptor = args.TrackDescriptor;
            if (trackDescriptor is EventTrackDescriptor)
            {
                EventTrackDescriptor eventTrackDescriptor = (EventTrackDescriptor)trackDescriptor;
                if (eventTrackDescriptor.Definition.Id.Equals(new Guid(("{A6202545-323F-42ED-B904-81079C762524}")))
                {
                    if (Sitecore.Analytics.Tracker.Current != null &amp;&amp; Sitecore.Analytics.Tracker.Current.Contact != null)
                    {
                        UpdateandIdenifyContact(eventTrackDescriptor);
                    }
                    else
                    {
                        Log.Info("cannot found the contact for the current interaction", this);
                    }
                }
                else
                {
                    this.TriggerPageEvent((IDefinition)eventTrackDescriptor.Definition, currentPageContext, eventTrackDescriptor.Data, eventTrackDescriptor.DataKey, eventTrackDescriptor.Extras);
                }
            }
            else if (trackDescriptor is GoalTrackDescriptor)
            {
                GoalTrackDescriptor goalTrackDescriptor = (GoalTrackDescriptor)trackDescriptor;
                this.TriggerPageEvent((IDefinition)goalTrackDescriptor.Definition, currentPageContext, goalTrackDescriptor.Data, goalTrackDescriptor.DataKey, goalTrackDescriptor.Extras);
            }
            else if (trackDescriptor is CampaignTrackDescriptor)
            {
                CampaignTrackDescriptor campaignTrackDescriptor = (CampaignTrackDescriptor)trackDescriptor;
                currentPageContext.TriggerCampaign(campaignTrackDescriptor.Definition);
            }
            else if (trackDescriptor is OutcomeTrackDescriptor)
            {
                OutcomeTrackDescriptor outcomeTrackDescriptor = (OutcomeTrackDescriptor)trackDescriptor;
                OutcomeData outcome = new OutcomeData(outcomeTrackDescriptor.Definition, outcomeTrackDescriptor.CurrencyCode, outcomeTrackDescriptor.Monetary);
                IDictionary&lt;string, string&gt; extras = outcomeTrackDescriptor.Extras;
                if (extras != null &amp;&amp; extras.Count &gt; 0)
                    outcome.CustomValues["FXM_CustomValues"] = (object)outcomeTrackDescriptor.Extras;
                currentPageContext.RegisterOutcome(outcome);
            }
            else
            {
                if (!(trackDescriptor is ElementMatcherTrackDescriptor))
                    return;
                this.TriggerElement(((ElementMatcherTrackDescriptor)trackDescriptor).Item, currentPageContext);
            }
        }

        private void UpdateandIdenifyContact(EventTrackDescriptor eventTrackDescriptor)
        {
            try
            {
                Assert.IsTrue(eventTrackDescriptor.Extras.Any(), "FXM JS API - Parameter not passed");
                if (eventTrackDescriptor.Extras != null &amp;&amp; eventTrackDescriptor.Extras.Any())
                {
                    var values = eventTrackDescriptor.Extras;
                    Assert.IsTrue(values.ContainsKey("uniqueId"), "FXM JS API - Parameter - uniqueId not passed");
                    Assert.IsNotNullOrEmpty(values["uniqueId"], "FXM JS API - Parameter - uniqueId in Empty");
                    if (values.ContainsKey("uniqueId") &amp;&amp; !string.IsNullOrEmpty(values["uniqueId"]))
                    {
                        using (XConnectClient client = SitecoreXConnectClientConfiguration.GetClient())
                        {
                            ContactExpandOptions Facets = new ContactExpandOptions(new string[] {
                            PersonalInformation.DefaultFacetKey,
                            EmailAddressList.DefaultFacetKey,
                            PayLoad.DefaultFacetKey
                            });
                            Sitecore.XConnect.Contact contact = client.Get(new IdentifiedContactReference("ContactPayload", values["uniqueId"].ToString().ToLowerInvariant()), Facets);
                            PersonalInformation PersonalFacet;
                            EmailAddressList EmailAddressListFacet = null;
                            PayLoad PayLoadFacet = null;
                            var manager = Sitecore.Configuration.Factory.CreateObject("tracking/contactManager", true) as Sitecore.Analytics.Tracking.ContactManager;
                            if (contact == null) //if the contact is not existing in the system
                            {
                                contact = new Sitecore.XConnect.Contact(new ContactIdentifier("ContactPayload", values["uniqueId"].ToString().ToLowerInvariant(), ContactIdentifierType.Known));
                                client.AddContact(contact);
                                PayLoadFacet = new PayLoad();
                                FillPayload(PayLoadFacet, eventTrackDescriptor);
                                if (!string.IsNullOrEmpty(PayLoadFacet.FirstName))
                                {
                                    PersonalFacet = new PersonalInformation()
                                    {
                                        FirstName = PayLoadFacet.FirstName,
                                        LastName = PayLoadFacet.LastName
                                    };
                                    client.SetFacet(contact, PersonalInformation.DefaultFacetKey, PersonalFacet);
                                }
                                if (!string.IsNullOrEmpty(PayLoadFacet.Email))
                                {
                                    EmailAddressListFacet = new EmailAddressList(new EmailAddress(PayLoadFacet.Email, true), "Preferred");
                                    client.SetFacet(contact, EmailAddressList.DefaultFacetKey, EmailAddressListFacet);
                                }
                            }
                            else
                            {
                                PayLoadFacet = contact.GetFacet(PayLoad.DefaultFacetKey);
                                if (PayLoadFacet == null)
                                    PayLoadFacet = new PayLoad();
                                FillPayload(PayLoadFacet, eventTrackDescriptor);
                                if (!string.IsNullOrEmpty(PayLoadFacet.FirstName))
                                {
                                    PersonalFacet = contact.GetFacet(PersonalInformation.DefaultFacetKey);
                                    if (PersonalFacet == null)
                                    {
                                        PersonalFacet = new PersonalInformation()
                                        {
                                            FirstName = PayLoadFacet.FirstName,
                                            LastName = PayLoadFacet.LastName
                                        };
                                    }
                                    else
                                    {
                                        PersonalFacet.FirstName = PayLoadFacet.FirstName;
                                        PersonalFacet.LastName = PayLoadFacet.LastName;
                                    }
                                    client.SetFacet(contact, PersonalInformation.DefaultFacetKey, PersonalFacet);
                                }
                                if (!string.IsNullOrEmpty(PayLoadFacet.Email))
                                {
                                    EmailAddressListFacet = contact.GetFacet(EmailAddressList.DefaultFacetKey);
                                    if (EmailAddressListFacet == null)
                                        EmailAddressListFacet = new EmailAddressList(new EmailAddress(PayLoadFacet.Email, true), "Preferred");
                                    else
                                        EmailAddressListFacet.PreferredEmail = new EmailAddress(PayLoadFacet.Email, true);

                                    client.SetFacet(contact, EmailAddressList.DefaultFacetKey, EmailAddressListFacet);
                                }
                            }
                            client.SetFacet(contact, PayLoad.DefaultFacetKey, PayLoadFacet);
                            client.Submit();
                            manager.RemoveFromSession(Tracker.Current.Session.Contact.ContactId);
                            Tracker.Current.Session.IdentifyAs("ContactPayload", values["uniqueId"].ToString().ToLowerInvariant());
                            Tracker.Current.Session.Contact = manager.LoadContact(Tracker.Current.Contact.ContactId);
                            Log.Info("FXM JS API added contact "+ Tracker.Current.Contact.ContactId.ToString() + " for " + values["uniqueId"].ToString().ToLowerInvariant(), "FXM JS API");
                        }
                    }
                    else
                    {
                       Log.Error("FXM JS API - Parameter - uniqueId not passed", "FXM JS API");
                    }
                }
                else
                {
                    Log.Error("FXM JS API - Parameters not passed", "FXM JS API");
                }
            }
            catch (XdbExecutionException ex)
            {
                Log.Error("XDB Exception while adding or updating contacts " + ex.Message, ex, this);
                throw ex;
            }
            catch (System.AggregateException ae)
            {
                foreach (var e in ae.Flatten().InnerExceptions)
                {
                    Log.Error("Aggregate Error while adding or updating contacts " + e.Message, e, this);
                }
                throw ae;
            }
            catch (Exception ex)
            {
                Log.Error("Exception while adding or updating contacts " + ex.Message, ex ,this);
                throw ex;
            }
        }
        private void FillPayload(PayLoad payloadinfo, EventTrackDescriptor eventTrackDescriptor)
        {
            var values = eventTrackDescriptor.Extras;
            payloadinfo.UniqueId = values.ContainsKey("uniqueId") ? values["uniqueId"].ToString().ToLowerInvariant() : string.Empty;
            payloadinfo.CustomerName = values.ContainsKey("customerName") ? values["customerName"].ToString() : string.Empty;
            payloadinfo.FirstName = values.ContainsKey("firstName") ? values["firstName"].ToString() : string.Empty;
            payloadinfo.LastName = values.ContainsKey("lastName") ? values["lastName"].ToString() : string.Empty;
            payloadinfo.Email = values.ContainsKey("email") ? values["email"].ToString() : string.Empty;         
            payloadinfo.Language = values.ContainsKey("language") ? values["language"].ToString().ToLowerInvariant() : "en";
        }
    }</code></pre>
<p>As you could see that even though I have inherited the Sitecore default TriggerEventsProcessor, I have used Process() method as is, instead of overriding with a check for the event’s definition as CONTACTEVENT({A6202545-323F-42ED-B904-81079C762524}) to update and Identify Contact. This will make sure that the default page event is not triggered when there is a huge amount of call to update contact via trackevent of beacon script from an external site.<br />
The next step is to register the custom processor in Sitecore configuration using Sitecore config patching standard practice.</p>
<pre><code>&lt;configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/" &gt;
 &lt;sitecore&gt;
  &lt;pipelines&gt;
   &lt;group name="FXM" groupName="FXM" &gt;
    &lt;pipelines&gt;
     &lt;tracking.triggerpageevent&gt;
      &lt;processor type="Project.Standalone.FXM.Pipelines.Tracking.TriggerFXMEventsProcessor, Project.Standalone" patch:instead="processor[@type='Sitecore.FXM.Pipelines.Tracking.TriggerPageEvent.TriggerEventsProcessor, Sitecore.FXM']" resolve="true"/&gt;
     &lt;/tracking.triggerpageevent&gt;
    &lt;/pipelines&gt;
   &lt;/group&gt;
  &lt;/pipelines&gt;
 &lt;/sitecore&gt;
&lt;/configuration&gt;</code></pre>
<p>Once the custom processor is registered, we need to&nbsp;create the CONTACTEVENT ({A6202545-323F-42ED-B904-81079C762524}) page&nbsp;event items in Sitecore. Navigate to /Sitecore/system/Settings/Analytics/Page Events path in the content tree and create page event as described below.<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-4393" src="https://www.symsoftsolutions.com/wp-content/uploads/2020/01/Contactevent.png" alt="Contact Event" width="624" height="388"></p>
<p>Now we can call the trackevent method after the load of the beacon script. There are different ways (refer to&nbsp;<a href="https://doc.sitecore.com/developers/91/sitecore-experience-platform/en/fxm-javascript-api.html" target="_blank" rel="noopener">Sitecore documentation</a>) to pass the updated contact data to the page event, it also depends on your implementation. I decided to use an extra dictionary of EventTrackDescriptor to send the contact details. To test you can call the trackEvent method in the developer console of your browser, once FXM script is loaded on the External Site.</p>
<pre><code>SCBeacon.trackEvent("contactevent", {
                     xuniqueId: "0001181764-288089",
                     xcustomerName: "NICOLE TREJOS",
                     xfirstName: "NICOLE",
                     xlastName: "TREJOS",
                     xemail: "NICOLE.TREJOS@test.com",
                     xlanguage: "en"
                   });</code></pre>
<p>You can see the new contact added using Experience Profile.<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-4395" src="https://www.symsoftsolutions.com/wp-content/uploads/2020/01/experienceprofile.png" alt="Experience Profile" width="624" height="193"></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Sitecore 9.X Intranet Login using Azure Active Directory</title>
		<link>https://www.symsoftsolutions.com/sitecore/sitecore-9-azure-active-directory/</link>
		
		<dc:creator><![CDATA[Terence Jones]]></dc:creator>
		<pubDate>Thu, 02 Jan 2020 19:01:34 +0000</pubDate>
				<category><![CDATA[Sitecore]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=4333</guid>

					<description><![CDATA[]]></description>
										<content:encoded><![CDATA[<p><div class="et_pb_section et_pb_section_0 et_section_regular" >
				
				
				
				
				
				
				<div class="et_pb_row et_pb_row_0">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_0  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_0  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h3>Summary</h3>
<p>I am using <strong><a href="/sitecore/">Sitecore</a></strong> for a Multisite that is already hosting two publicly available sites. We wanted to create a new intranet site using the same instance of Sitecore. Since this is an internal site one of the requirements was to secure all content using Azure Active Directory, keep in mind we are not talking about the Sitecore Client, but the actual site. So to sum up the challenge: Secure the intranet using Azure Active Directory while leaving the other two public sites available to all. We also wanted to use Microsoft Graph API (Delegated) to update their intranet profile immediately after the user logs in using AAD and using an OAuth Token, but we will tackle that in a later blog post.</p>
<p>The following steps will be outlined below:</p>
<ul>
<li class="code-line code-line" data-line="6">Turning on Sitecore&#8217;s Federated Authentication</li>
<li class="code-line code-line" data-line="7">Building a custom IdentityProvidersProcessor for Azure AD or OpenId</li>
<li class="code-line code-line" data-line="8">Coding Azure AD Identity Provider</li>
<li class="code-line code-line" data-line="9">Mapping Claims</li>
<li class="code-line code-line" data-line="10">Creating a Sitecore User Builder</li>
<li class="code-line code-line" data-line="11">Setup the AppRegistration in Azure Active Directory</li>
<li class="code-line code-line" data-line="11">Forcing Intranet Site to use login</li>
</ul></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_1">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_1  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_1  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h3 id="turning-on-sitecores-federated-authentication" class="code-line code-line" data-line="13">Turning on Sitecore&#8217;s Federated Authentication</h3>
<p class="code-line code-line" data-line="14">The following config will enable Sitecore&#8217;s federated authentication. This configuration is also located in an example file located in \\App_Config\\Include\\Examples\\Sitecore.Owin.Authentication.Enabler.example. I decided to create my own patch file and install it in the Include folder.</p></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_2">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_2  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_2  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:role="http://www.sitecore.net/xmlconfig/role/"  xmlns:env="http://www.sitecore.net/xmlconfig/env/"&gt;
  &lt;sitecore&gt;
        &lt;settings&gt;
            &lt;setting name="FederatedAuthentication.Enabled"&gt;
              &lt;patch:attribute name="value"&gt;true&lt;/patch:attribute&gt;
            &lt;/setting&gt;
        &lt;/settings&gt;
        &lt;services&gt;
            &lt;register serviceType="Sitecore.Abstractions.BaseAuthenticationManager, Sitecore.Kernel"
                      implementationType="Sitecore.Owin.Authentication.Security.AuthenticationManager, Sitecore.Owin.Authentication"
                      lifetime="Singleton" /&gt;
            &lt;register serviceType="Sitecore.Abstractions.BaseTicketManager, Sitecore.Kernel"
                      implementationType="Sitecore.Owin.Authentication.Security.TicketManager, Sitecore.Owin.Authentication"
                      lifetime="Singleton" /&gt;
            &lt;register serviceType="Sitecore.Abstractions.BasePreviewManager, Sitecore.Kernel"
                      implementationType="Sitecore.Owin.Authentication.Publishing.PreviewManager, Sitecore.Owin.Authentication"
                      lifetime="Singleton" /&gt;
        &lt;/services&gt;
    &lt;/sitecore&gt;
&lt;/configuration&gt;
</pre></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_3">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_3  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_3  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h3 id="identityprovidersprocessor-for-azure-ad-using-the-openid-protocol" class="code-line code-line" data-line="39">IdentityProvidersProcessor for Azure AD using the OpenId Protocol</h3>
<blockquote class="code-line code-line" data-line="40">
<p class="code-line code-line" data-line="40">The following Class inherits Sitecore&#8217;s IdentityProvidersProcessor</p>
</blockquote>
<pre>using Owin;
using Sitecore.Configuration;
using Sitecore.Diagnostics;
using Sitecore.Owin.Authentication.Configuration;
using Sitecore.Owin.Authentication.Pipelines.IdentityProviders;
using Sitecore.Owin.Authentication.Services;
using System.Globalization;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OpenIdConnect;

namespace Foundation.Auth.Processors
{
    public class AzureADIdentityProviderProcessor : IdentityProvidersProcessor
    {

    }
}
The ProviderProcessor should override the IdentityProviderName property and the ProcessCore method

protected override void ProcessCore(IdentityProvidersArgs args)
{
            Assert.ArgumentNotNull(args, nameof(args));

            var identityProvider = this.GetIdentityProvider();
            var authenticationType = this.GetAuthenticationType();

            string aadInstance = Settings.GetSetting("AADInstance");
            string tenant = Settings.GetSetting("Tenant");
            string clientId = Settings.GetSetting("ClientId");
            string postLogoutRedirectURI = Settings.GetSetting("PostLogoutRedirectURI");
            string redirectURI = Settings.GetSetting("RedirectURI");
            string authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

            args.App.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
            {
                Caption = identityProvider.Caption,
                AuthenticationType = authenticationType,
                AuthenticationMode = AuthenticationMode.Passive,
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = postLogoutRedirectURI,
                RedirectUri = redirectURI,
                Scope = "offline_access",

                // Watch for Events
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    // When everything is passed
                    SecurityTokenValidated = async notification =&gt;
                    {
                        // Get the Ident object from Ticket
                        var identity = notification.AuthenticationTicket.Identity;

                        // Use Sitecore Claim Transformation Service to generate additional claims like role or admin
                        foreach (var claimTransformationService in identityProvider.Transformations)
                        {
                            claimTransformationService.Transform(identity,
                                new TransformationContext(FederatedAuthenticationConfiguration,identityProvider));
                        }

                        // Create new Auth Ticket
                        notification.AuthenticationTicket = new AuthenticationTicket(identity, notification.AuthenticationTicket.Properties);

                        //Returns blank task
                        return; 
                    }

                }
            });
        }</pre>
<p class="code-line code-line" data-line="114">The <strong><em>ProcessCore</em></strong> method should look familiar if you have used OWIN middleware in other .NET projects and used IAppBuilder. This method sets up the OpenId connect provider and also handles the SecurityTokenValidated event. This is also where we set up the endpoints and all the properties needed from the Azure AD Tenant. These settings are not hard coded, but pulled in from Sitecore settings config.</p>
<p class="code-line code-line" data-line="116">Within the <em><strong>SecurityTokenValidated</strong></em> anonymous function, Sitecore&#8217;s Claims transformation service is being used to map claims returned from AAD and mapped to Sitecore Claims. These newly created Sitecore claims will later be used to create a Sitecore user and log them in.</p>
<p class="code-line code-line" data-line="116">The following are examples of the settings:</p>
<pre>&lt;sitecore role:require="Standalone or ContentDelivery or ContentManagement"&gt;
    
    &lt;!-- Common Settings Should be same for each Environment --&gt;
    &lt;settings&gt;
      &lt;setting name="AADInstance" value="https://login.microsoftonline.com/{0}" /&gt;
      &lt;setting name="AuthorityUri" value="https://login.microsoftonline.com/common/" /&gt;
    &lt;/settings&gt;
    
    &lt;!-- Settings for Local --&gt;
    &lt;settings env:require="Local"&gt;
      &lt;setting name="ClientId" value="XXXXX-3586-XXX-XXX-4XXXXXd2a18" /&gt;
      &lt;setting name="ClientSecret" value="Goblyhash" /&gt;
      &lt;setting name="Tenant" value="yourtenant.com" /&gt;
      &lt;setting name="PostLogoutRedirectURI" value="https://intranet.local/sitecore/login"/&gt;
      &lt;setting name="RedirectURI" value="https://intranet.local/sitecore" /&gt;
    &lt;/settings&gt;
</pre></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_4">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_4  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_4  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h3 id="user-builder" class="code-line code-line" data-line="118">User Builder</h3>
<p class="code-line code-line" data-line="119">Because we are using Sitecore Federated authentication, the creation of Sitecore users is handled automatically. Sitecore does, however, give you the opportunity to inject your own custom user builder. This is great because I wanted to be able to control which domain the intranet users were assigned.</p>
<p class="code-line code-line" data-line="121">I inherited the <em><strong>DefaultExternalUserBuilder</strong></em> then rewrote the domain name in the <em><strong>CreateUniqueUserName </strong></em>method.</p>
<pre>using Microsoft.AspNet.Identity;
using Sitecore.Diagnostics;
using Sitecore.Owin.Authentication.Configuration;
using Sitecore.Owin.Authentication.Identity;
using System;

namespace Foundation.Auth.UserBuilder
{
    public class IntranetUserBuilder : Sitecore.Owin.Authentication.Services.DefaultExternalUserBuilder
    {
        public IntranetUserBuilder(bool isPersistentUser) :base(isPersistentUser)
        {
        }

        public IntranetUserBuilder(string isPersistentUser) : base(bool.Parse(isPersistentUser))
        {
        }

        protected override string CreateUniqueUserName(UserManager userManager, Microsoft.AspNet.Identity.Owin.ExternalLoginInfo externalLoginInfo)
        {
            Assert.ArgumentNotNull((object)userManager, nameof(userManager));
            Assert.ArgumentNotNull((object)externalLoginInfo, nameof(externalLoginInfo));
            IdentityProvider identityProvider = this.FederatedAuthenticationConfiguration.GetIdentityProvider(externalLoginInfo.ExternalIdentity);
            if (identityProvider == null)
                throw new InvalidOperationException("Unable to retrieve identity provider for given identity");
            string domain = identityProvider.Domain;
            string email = externalLoginInfo.DefaultUserName;

            // return email and domain
            return $"{domain}\\\\\\\\{email}";

        }

    }
}
</pre></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_5">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_5  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_5  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h3 id="configuring-the-user-builder" class="code-line code-line" data-line="161">Configuring the User Builder</h3>
<p>Now that we have created a custom user builder we will need to teach Sitecore how to use it, with the following config, although the <em><strong>IdentityProvidersPerSites </strong></em>element also tells Sitecore which Site Definitions are using the custom IdentityProvider</p>
<pre>&lt;identityProvidersPerSites&gt;
        &lt;mapEntry name="all" type="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication"&gt;
          &lt;sites hint="list"&gt;
            &lt;site&gt;intranet&lt;/site&gt;
          &lt;/sites&gt;
          &lt;!-- Registered identity providers for above providers --&gt;
          &lt;identityProviders hint="list:AddIdentityProvider"&gt;
            &lt;identityProvider ref="federatedAuthentication/identityProviders/identityProvider[@id='azureAD']" /&gt;
          &lt;/identityProviders&gt;
          &lt;!-- ExternalUserBuilder is what creates a user with custom username in Sitecore and assigns roles based on claim transformation configured above --&gt;
          &lt;externalUserBuilder type="Foundation.Auth.UserBuilder.IntranetUserBuilder, Foundation.Auth"&gt;
            &lt;param desc="isPersistentUser"&gt;true&lt;/param&gt;
          &lt;/externalUserBuilder&gt;
        &lt;/mapEntry&gt;
      &lt;/identityProvidersPerSites&gt;
&lt;/federatedAuthentication&gt;
</pre>
<p>Note that the <em><strong>externalUserBuilder</strong></em> is pointed to our custom user builder. Also note that the parameter <em><strong>isPersistentUser</strong></em> is set to <strong><em>true</em></strong> which tells Sitecore&#8217;s user builder to create a permanent user rather then a virtual user in Sitecore. Refer to Sitecore&#8217;s documentation about when to use Virtual Users or Persistent Users. </div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_6">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_6  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_6  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h3 id="configuring-the-auth" class="code-line code-line" data-line="182">Configuring the Auth</h3>
<p>We need to tell Sitecore to use our Azure Identity Provider with the following configuration.</p>
<pre>&lt;pipelines&gt;
      &lt;owin.identityProviders&gt;
        &lt;!-- This is the custom processor that gets executed when azure AD posts the token to Sitecore --&gt;
        &lt;processor type="Foundation.Auth.Processors.AzureADIdentityProviderProcessor, Foundation.Auth" resolve="true" /&gt;
      &lt;/owin.identityProviders&gt;
&lt;/pipelines&gt;
</pre>
<p>And the following configuration tells Sitecore how to map Claims from AAD into Sitecore.</p>
<pre>&lt;federatedAuthentication&gt;
      &lt;!-- Property initializer assigns claim values to sitecore user properties --&gt;
      &lt;propertyInitializer type="Sitecore.Owin.Authentication.Services.PropertyInitializer, Sitecore.Owin.Authentication"&gt;
        &lt;patch:attribute name="type"&gt;Foundation.Auth.UserBuilder.UserPropertyInitializer, Foundation.Auth&lt;/patch:attribute&gt;
        &lt;maps hint="list"&gt;
          &lt;map name="email claim" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication"&gt;
            &lt;data hint="raw:AddData"&gt;
              &lt;!--claim name--&gt;
              &lt;source name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" /&gt;
              &lt;!--property name--&gt;
              &lt;target name="Email" /&gt;
            &lt;/data&gt;
          &lt;/map&gt;
          &lt;map name="Name claim" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication"&gt;
            &lt;data hint="raw:AddData"&gt;
              &lt;!--claim name--&gt;
              &lt;source name="name" /&gt;
              &lt;!--property name--&gt;
              &lt;target name="Fullname" /&gt;
            &lt;/data&gt;
          &lt;/map&gt;
          &lt;map name="Other claim" type="Sitecore.Owin.Authentication.Services.DefaultClaimToPropertyMapper, Sitecore.Owin.Authentication"&gt;
            &lt;data hint="raw:AddData"&gt;
              &lt;!--claim name--&gt;
              &lt;source name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" /&gt;
              &lt;!--property name--&gt;
              &lt;target name="Comment" /&gt;
            &lt;/data&gt;
          &lt;/map&gt;
        &lt;/maps&gt;
      &lt;/propertyInitializer&gt;
    &lt;/federatedAuthentication&gt;
</pre>
<blockquote class="code-line code-line" data-line="40">
<p class="code-line code-line" data-line="40">The example above maps Azure&#8217;s UPN to Sitecore&#8217;s Email field and Azure&#8217;s Name Field into Sitecore&#8217;s Fullname Field</p>
</blockquote>
<h3 class="code-line code-line" data-line="40">Register the new Identity Provider with Sitecore</h3>
<pre>&lt;identityProviders hin="list:AddIdentityProvider"&gt;
        &lt;identityProvider id="azureAD" type="Sitecore.Owin.Authentication.Configuration.DefaultIdentityProvider, Sitecore.Owin.Authentication"&gt;
          &lt;param desc="name"&gt;$(id)&lt;/param&gt;
          &lt;param desc="domainManager" type="Sitecore.Abstractions.BaseDomainManager" resolve="true" /&gt;
          &lt;caption&gt;Sign-in with Azure Active Directory&lt;/caption&gt;
          &lt;domain&gt;intranet&lt;/domain&gt;
          &lt;icon&gt;/sitecore/shell/themes/standard/Images/24x24/msazure.png&lt;/icon&gt;
          &lt;transformations hint="list:AddTransformation"&gt;
            &lt;!-- you need to have and Idp Claim for this to work --&gt;
            &lt;transformation name="Idp Claim" ref="federatedAuthentication/sharedTransformations/setIdpClaim" /&gt;
            &lt;!-- This is to transform your Azure group into Sitecore Role. The claim value below is the object id of the role that needs to be copied from Azure --&gt;
            &lt;transformation name="devRole" type="Sitecore.Owin.Authentication.Services.DefaultTransformation, Sitecore.Owin.Authentication"&gt;
              &lt;sources hint="raw:AddSource"&gt;
                &lt;claim name="groups" value="9ae0af64-3b5b-45b7-b6e8-62a613250824" /&gt;
              &lt;/sources&gt;
              &lt;targets hint="raw:AddTarget"&gt;
                &lt;claim name="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" value="Sitecore\\Developer" /&gt;
              &lt;/targets&gt;
              &lt;keepSource&gt;true&lt;/keepSource&gt;
            &lt;/transformation&gt;
          &lt;/transformations&gt;
        &lt;/identityProvider&gt;
      &lt;/identityProviders&gt;
Assign Identity Providers the intranet site

&lt;identityProvidersPerSites&gt;
        &lt;mapEntry name="all" type="Sitecore.Owin.Authentication.Collections.IdentityProvidersPerSitesMapEntry, Sitecore.Owin.Authentication"&gt;
          &lt;sites hint="list"&gt;
            &lt;site&gt;intranet&lt;/site&gt;
          &lt;/sites&gt;
          &lt;!-- Registered identity providers for above providers --&gt;
          &lt;identityProviders hint="list:AddIdentityProvider"&gt;
            &lt;identityProvider ref="federatedAuthentication/identityProviders/identityProvider[@id='azureAD']" /&gt;
          &lt;/identityProviders&gt;
        &lt;/mapEntry&gt;
      &lt;/identityProvidersPerSites&gt;
</pre></div>
			</div><div class="et_pb_module et_pb_text et_pb_text_7  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><h3>Forcing a Login</h3>
<p>On the Site Definition we need to tell Sitecore where the login Page is located effectively putting that site behind a login wall. We did not want to the Sitecore Login page as a Idp Portal so I whipped up a custom aspx page that is publicly available</p>
<blockquote><p>Here is the SiteDefinition Example</p></blockquote>
<pre>      &lt;site name="intranet" patch:before="site[@name='website']"
         enableTracking="true"
         scheme="https"
         hostName="www.intranet.com"
         virtualFolder="/"
         physicalFolder="/"
         rootPath="/sitecore/content"
         startItem="/Intranet"
         database="web"
         domain="intranet"
         allowDebug="true"
         cacheHtml="true"
         filteredItemsCacheSize="10MB"
         enablePreview="true"
         enableWebEdit="true"
         enableDebugger="true"
         disableClientData="false"
         requireLogin="true"
         loginPage="/sitecore/login/IntranetLogin.aspx"  /&gt;
</pre>
<blockquote><p>And the following code is how the login functions</p></blockquote>
<pre>[AllowDependencyInjection]
    public partial class IntranetLogin : Page
    {
        // The Injected CorePipeline
        private BaseCorePipelineManager CorePipelineManager;

        public IntranetLogin()
        {
        }      

<span style="font-size: 16px;">       public IntranetLogin(BaseCorePipelineManager corePipelineManager)</span>
        {
            this.CorePipelineManager = corePipelineManager;
        }

<span style="font-size: 16px;">        protected override void OnInit(EventArgs e)</span>
        {
            RedirectToIdp();
            base.OnInit(e);
        }

<span style="font-size: 16px;">        internal void RedirectToIdp()</span>
        {
<span style="font-size: 16px;">            //Run Pipeline to get list of external logins</span>
            GetSignInUrlInfoArgs args = new GetSignInUrlInfoArgs("intranet", WebUtil.GetQueryString("returnUrl"));
            GetSignInUrlInfoPipeline.Run(this.CorePipelineManager, args);

<span style="font-size: 16px;">            //Get link to IDP</span>
            var redirectToIdp = args.Result.First().Href;

<span style="font-size: 16px;">            //Response.Redirect(redirectToIdp);</span>
           PostRedirect(redirectToIdp);

       }

<span style="font-size: 16px;">       private void PostRedirect(string url)</span>
        {
            Response.Clear();
            var sb = new System.Text.StringBuilder();
            sb.Append("&lt;html&gt;");
            sb.AppendFormat("&lt;body onload='document.forms[0].submit()'&gt;");
            sb.AppendFormat("&lt;form action='{0}' method='post'&gt;", url);
            sb.Append("&lt;/form&gt;");
            sb.Append("&lt;/body&gt;");
            sb.Append("&lt;/html&gt;");
            Response.Write(sb.ToString());
            Response.End();
       }
       
      internal SignInUrlInfo PrepareSignInInfo(SignInUrlInfo info)
      {
            int num = info.Href.IndexOf("?", StringComparison.Ordinal);
            string href = info.Href;
            if (num &gt; -1)
            {
               NameValueCollection queryString1 = HttpUtility.ParseQueryString(info.Href.Substring(num + 1));
                NameValueCollection queryString2 = HttpUtility.ParseQueryString(string.Empty);
                foreach (string key in queryString1.Keys)
                    queryString2[key] = HttpUtility.UrlEncode(queryString1[key]);
                href = info.Href.Substring(0, num + 1) + (object)queryString2;
            }
            return new SignInUrlInfo(info.IdentityProvider, href, info.Caption, info.Icon);
        }

}</pre></div>
			</div>
			</div>
				
				
				
				
			</div><div class="et_pb_row et_pb_row_7">
				<div class="et_pb_column et_pb_column_4_4 et_pb_column_7  et_pb_css_mix_blend_mode_passthrough et-last-child">
				
				
				
				
				<div class="et_pb_module et_pb_text et_pb_text_8  et_pb_text_align_left et_pb_bg_layout_light">
				
				
				
				
				<div class="et_pb_text_inner"><p>Once everything is all wired up, the login should work as expected. Finito!</p>
<p>&nbsp;</p>
<h2>Need help with integrating Azure Active Directory as a log-in option for Sitecore?</h2>
<p>We have extensive experience with <strong><a href="/sitecore/">3rd-party Sitecore integrations</a></strong>. Feel free to <strong><a href="/contact/">reach out to us</a></strong> if you have questions or need assistance with your Sitecore implementation.</p></div>
			</div>
			</div>
				
				
				
				
			</div>
				
				
			</div></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Solr POST request not working in Sitecore 9.1</title>
		<link>https://www.symsoftsolutions.com/sitecore/solr-post-request-not-working-in-sitecore-9-1/</link>
		
		<dc:creator><![CDATA[Pushkal Shetty]]></dc:creator>
		<pubDate>Mon, 30 Dec 2019 22:20:50 +0000</pubDate>
				<category><![CDATA[Sitecore]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=4312</guid>

					<description><![CDATA[We recently had to upgrade one of our client’s Sitecore website from version 8.2 to 9.1. During the upgrade we noticed that a POST request that was being used for one of the search components stopped working. The following error was being written to the Sitecore logs: “Error: Invalid URI: The Uri string is too [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>We recently had to upgrade one of our client’s Sitecore website from version 8.2 to 9.1. During the upgrade we noticed that a POST request that was being used for one of the search components stopped working. The following error was being written to the Sitecore logs:</p>
<blockquote><p>“Error: Invalid URI: The Uri string is too long.</p>
<p>The remote server returned an error: (414) Request-URI Too Long”</p></blockquote>
<p>Looking at the configurations for SItecore 8.2 we noticed that Solr’s default request was set to POST by using a Sitecore support package as POST requests were not officially supported for that version of Sitecore. They were using the support package because they faced the same issue of the request size being too large for a GET request. And, this support package no longer seemed to work with version 9.1.</p>
<p>After looking around online I found articles pointing to a setting “ContentSearch.Solr.SendPostRequests” in the configuration file “C:\inetpub\wwwroot\trc91.local\App_Config\Sitecore\ContentSearch\Sitecore.ContentSearch.Solr.DefaultIndexConfiguration.config” and setting the value to true, should enable POST requests on Solr. Unfortunately, this didn’t work as we noticed that the search query was still being sent as a GET request. So, it seemed to have been working only for version 9.0 and not 9.1 (I have not tested this on 9.0).</p>
<p>Therefore, our next step was to reach out to Sitecore Support and they confirmed that the setting mentioned above doesn’t work and they have no plans of fixing it in the near future.</p>
<p>Instead, they gave us a workaround, to change the “requestHeaderSIze” attribute value to a higher value in the following file on your Solr server “[solr]/server/etc” (we set the value to 29000). Setting this value will allow Solr to support larger sizes for GET requests. It should look like this:</p>
<blockquote><p>&lt;Set name=&#8221;requestHeaderSize&#8221;&gt;&lt;Property name=&#8221;solr.jetty.request.header.size&#8221; default=&#8221;29000&#8243; /&gt;&lt;/Set&gt;</p></blockquote>
<p>We tried this workaround and we could confirm that the search component started working again. I hope this blog will help other Sitecore developers who might face a similar issue.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Advanced Search Experience with Sitecore and Solr</title>
		<link>https://www.symsoftsolutions.com/sitecore/advanced-search-experience-with-sitecore-and-solr/</link>
		
		<dc:creator><![CDATA[SymSoft Solutions]]></dc:creator>
		<pubDate>Mon, 01 Apr 2019 21:28:12 +0000</pubDate>
				<category><![CDATA[Sitecore]]></category>
		<category><![CDATA[Digital Experience]]></category>
		<category><![CDATA[User Experience Design]]></category>
		<guid isPermaLink="false">https://www.symsoftsolutions.com/?p=4166</guid>

					<description><![CDATA[Google-like search experience is so ubiquitous nowadays, that as end users we hardly ever notice it. It allows us to misspell words, expand our exploration beyond the initial scope, or simply provide answers to specific questions. Yet, those familiar with the Tesler’s Law of Preservation of Complexity know that most simple user experiences are in [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>Google-like search experience is so ubiquitous nowadays, that as end users we hardly ever notice it. It allows us to misspell words, expand our exploration beyond the initial scope, or simply provide answers to specific questions. Yet, those familiar with the <a href="https://en.wikipedia.org/wiki/Law_of_conservation_of_complexity" target="_blank" rel="noopener"><strong>Tesler’s Law of Preservation of Complexity</strong></a> know that most simple user experiences are in many cases quite elaborate pieces of elaborate design and engineering.</p>
<p>This article will provide you with a few examples of the advanced search experiences that are integrated with the <strong>Sitecore-based solutions</strong> we deliver to our customers, such as <a href="/case-studies/smud/"><strong>SMUD</strong></a>, <a href="/case-studies/california-department-of-water-resources-website-redesign/"><strong>DWR</strong></a> and <a href="/case-studies/california-department-of-general-services/"><strong>DGS</strong></a>.</p>
<p>Sitecore Content Search API is responsible for communicating with search engine software such as <a href="http://lucene.apache.org/solr/" target="_blank" rel="noopener"><strong>Solr</strong></a>, a popular enterprise-level platform built on Apache Lucene™. Out of the box, the Content Search API retrieves the basic list of results, which works perfectly if the end user knows exactly what they are looking for. It’s a little less convenient for people who are not quite sure what they need, or simply don’t even know how to phrase the query.</p>
<p>SymSoft improves the original Sitecore Content Search API by adding methods that can retrieve other information — such as alternative query suggestion, or query term highlights in the list of results. This creates the user experience similar to the one provided by Google Search.</p>
<p>Let’s see them in action.</p>
<h2>Alternative Query Suggestion</h2>
<p>Alternative query suggestion will attempt to search content with the original keyword. In case there are no results to display, it will suggest an alternative query results based on similar existing words or phrases. Below is an example of <a href="https://water.ca.gov/SearchResults?sort=relevance&amp;search=univorsity" target="_blank" rel="noopener"><strong>the alternative query suggestion</strong></a> on a live website for the California Department of Water Quality.</p>
<p><img loading="lazy" decoding="async" width="2277" height="1310" src="https://www.symsoftsolutions.com/wp-content/uploads/2019/04/dwr-alternative-query-suggestion-macbook.png" alt="Screenshot of DWR website search showcasing suggested alternative query results" class="alignnone size-full wp-image-4192"></p>
<h2>Stemmed Search</h2>
<p><a href="https://en.wikipedia.org/wiki/Stemming" target="_blank" rel="noopener"><strong>Stemmed search</strong></a> improves user experience by expanding query to include all results that are related to the base form of the word used in the query. In the example below, using keywords with the same root — <a href="https://water.ca.gov/SearchResults?sort=relevance&amp;search=university" target="_blank" rel="noopener"><strong>university</strong></a> and <a href="https://water.ca.gov/SearchResults?sort=relevance&amp;search=universities" target="_blank" rel="noopener"><strong>universities</strong></a> — will retrieve the same list of pages and documents (the root of the word <em>university</em> is <em>universit</em>).</p>
<p><img loading="lazy" decoding="async" width="2116" height="1959" src="https://www.symsoftsolutions.com/wp-content/uploads/2019/04/dwr-stemmed-search.png" alt="Screenshots of DWR search results page." class="alignnone size-full wp-image-4182"></p>
<h2>Query Term Highlighting</h2>
<p>Query term highlighting is useful in cases when the search query refers to multiple different contexts. Highlighted query terms help users understand the context around the keyword they were looking up. In the example below, it is easy to find documents that are related to different <a href="https://water.ca.gov/SearchResults?search=water+management&amp;tab=archivedocuments" target="_blank" rel="noopener"><strong>water management</strong></a> plans.</p>
<p><img loading="lazy" decoding="async" width="2277" height="1310" src="https://www.symsoftsolutions.com/wp-content/uploads/2019/04/dwr-keyword-highlights-macbook.png" alt="Screenshit of DWR search results showcasing keyword highlighting" class="alignnone size-full wp-image-4191"></p>
<h2>Conclusion</h2>
<p>This post hopefully illustrates how different advanced search functionalities can improve search experience for the end user. Furthermore, it demonstrates that a Sitecore-based website can be set up and customized to include advanced search features, especially when paired with a powerful search platform such as Solr.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
