Header Microsoft Dynamics 365 Field Service

Microsoft Dynamics 365 Field Service

Microsoft Dynamics 365 Field Service

Deliver excellent service and enhance customer experiences

Microsoft Dynamics 365 Field Service is the system that keeps you proactive in managing remote service operations with Field Service resources. It helps you run a more efficient and profitable service department. With the platform you can manage time, schedules, customer routes and reports, based on service intervals and available resources. This will optimize work process for your workers and increase communication and service towards your customers.

How Dynamics 365 Field Service helps your company

Real-time visibility

Real-time visibility


Gain real-time visibility into appointments and service statuses, enhancing customer satisfaction and operational efficiency.

Proactive management

Proactive management


Dynamics 365 Field Service empowers proactive management of remote service operations, ensuring efficiency and profitability.

Data-driven decisions

Data-driven decisions


Utilize insights from field service data to drive informed decisions and continuously improve service quality

Capabilities of Microsoft Dynamics 365 Field Service

Transform your field service management into a powerhouse of efficiency and innovation. Streamline workflows and enhance communication to keep your team and your customers connected and satisfied. Proactive maintenance ensures installations stay reliable, empowering your technicians to deliver smarter solutions while reducing costs.

By integrating installation data with field expertise, you gain a rock-solid foundation to optimize service intervals. It’s no longer about guesswork—it’s about precision, keeping your operations smooth and predictable.

Imagine always being one step ahead. Real-time data and forecasts give you a clear overview of upcoming tasks and routes. Stay agile, never miss a beat, and ensure your customers experience seamless service with no surprises.

Updated documentation is always at your fingertips, and your external technicians solve challenges confidently, backed by expert support from a centralized team.

The digital common thread

Seamless connectivity

Streamline the integration of data from IoT sensors, AR/VR devices, and various other sources directly within the Field Service system. Effortlessly track documentation, service intervals, and more, maximizing the benefits of an integrated approach to Field Service Management.

Enhanced planning and coordination

Microsoft Dynamics 365 Field Service optimizes the scheduling of Field Service activities. It enables you to allocate resources more effectively, increasing productivity, and minimizing travel times.

Real-time visibility

With a powerful customer portal based on Microsoft Power Apps, Dynamics 365 Field Service provides real-time visibility into appointments. This allows both you and your customers to closely monitor the status of services.

Automated communication

The software enables automated communication, keeping your customers informed with reminders and notifications via email and SMS. This enhances customer engagement and reduces the risk of miscommunication.

Efficient inventory management

Micorosft Dynamics 365 Field Service assists in managing inventory and materials, giving you better control over necessary resources. This minimizes unnecessary costs and improves inventory chain efficiency.

Data-driven decision-making

The software collects and analyzes data on field service activities, providing valuable insights that can be used for data-driven decision-making, process optimization, and continuous improvement.

Error executing template "Designs/Swift/Paragraph/9a_Content_gates_module.cshtml"
System.ArgumentException: field "$facets" was not indexed with SortedSetDocValues
   at Lucene.Net.Facet.SortedSet.DefaultSortedSetDocValuesReaderState..ctor(IndexReader reader, String field)
   at Dynamicweb.Indexing.Lucene.LuceneIndexProvider.<get_ReaderState>b__14_0(String path)
   at Dynamicweb.Indexing.Lucene.LuceneIndexProvider.SearchInternal(IQuery query, QuerySettings settings)
   at Dynamicweb.Indexing.Queries.IndexQueryProvider.Query(IQuery query, QuerySettings settings)
   at Dynamicweb.Indexing.Querying.QueryService.Query(IQuery query, QuerySettings settings)
   at NineAltitudes.CustomCode.NineAContent.ContentClient.NineAContentService.GetResults(Int32 pageSize, IQueryService queryService, IQuery query, Dictionary`2 parameters)
   at NineAltitudes.CustomCode.NineAContent.ContentClient.NineAContentService.GetContentByTagFilters(Int32 pageAreaId, IEnumerable`1 contentTypes, IEnumerable`1 tagFilters, Int32 pageSize)
   at CompiledRazorTemplates.Dynamic.RazorEngine_866ad1bd4baa483db592c78e5f8df5c5.GetFacetedContent(ParagraphViewModel model, Int32 maxItems, Int32 pageAreaId, String tagFilter)
   at CompiledRazorTemplates.Dynamic.RazorEngine_866ad1bd4baa483db592c78e5f8df5c5.ExecuteAsync()
   at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using NineAltitudes.CustomCode.NineAContent; 3 @using Dynamicweb.Rendering; 4 @using Dynamicweb.Extensibility; 5 @using Dynamicweb.Frontend; 6 @using System.Linq; 7 @using NineAltitudes.CustomCode.NineAContent.ContentClient; 8 9 @{ 10 const int maxItems = 7; 11 12 string title = Model.Item.GetString("Title"); 13 14 var filter = Dynamicweb.Context.Current.Request.QueryString.Get("filter"); 15 16 var pageView = Dynamicweb.Frontend.PageView.Current(); 17 int currentPageAreaId = pageView.AreaID; 18 19 (var content, var dimensions) = GetFacetedContent(Model, maxItems, currentPageAreaId, filter); 20 21 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 22 var decorations = Model.Item?.GetList("CssDecorations")?.GetRawValue().OfType<string>() ?? Enumerable.Empty<string>(); 23 24 string contentPadding = Model.Item.GetRawValueString("ContentPadding", "none"); 25 contentPadding = contentPadding == "none" ? "p-0" : contentPadding; 26 contentPadding = contentPadding == "small" ? "p-3 p-md-3" : contentPadding; 27 contentPadding = contentPadding == "large" ? "p-5 p-md-5" : contentPadding; 28 29 string buttonSize = Model.Item.GetString("ButtonSize") != "regular" ? Model.Item.GetString("ButtonSize") : String.Empty; 30 31 string buttonShape = "rounded-2"; 32 33 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 34 35 string cardTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("CardTheme")) ? " theme " + Model.Item.GetRawValueString("CardTheme").Replace(" ", "").Trim().ToLower() : ""; 36 string cardButtonText = Model.Item.GetString("CardButtonText"); 37 string cardButtonStyle = Model.Item.GetString("CardButtonStyle") == "btn-link" ? "btn-link ps-0" : Model.Item.GetString("CardButtonStyle"); 38 string cardButtonSize = Model.Item.GetString("CardButtonSize") != "regular" ? Model.Item.GetString("CardButtonSize") : String.Empty; 39 bool showCardButtonIcon = Model.Item.GetString("CardButtonType") == "icon" || Model.Item.GetString("CardButtonType") == "both"; 40 bool showCardButtonText = Model.Item.GetString("CardButtonType") == "text" || Model.Item.GetString("CardButtonType") == "both"; 41 string cardTitleSize = Model.Item.GetString("CardTitleSize"); 42 string cardShape = Model.Item.GetString("CardShape"); 43 string cardShapeCSS = cardShape == "boxed" ? "rounded-0" : "rounded-4"; 44 45 string ratio = Model.Item.GetString("ImageAspectRatio"); 46 ratio = ratio != "0" ? ratio : string.Empty; 47 string ratioCssClass = ratio != string.Empty ? " ratio" : string.Empty; 48 string ratioVariable = ratio != string.Empty ? "style=\"--bs-aspect-ratio: " + ratio + "\"" : string.Empty; 49 50 string secondChildOfGridCSS = content.Count == 5 || content.Count == 7 ? "grid g-col-12 g-col-lg-8" : "grid g-col-12"; 51 string secondChildOfGridChildCSS = content.Count == 5 ? "g-col-12 g-col-md-6" : content.Count == 7 ? "g-col-12 g-col-md-6 g-col-lg-4" : "g-col-12 g-col-md-6 g-col-lg-3"; 52 53 bool gridShouldBeSplit = (content.Count == 7 || content.Count == 5); 54 } 55 56 @functions { 57 58 private (List<Dynamicweb.Frontend.ItemViewModel> content, List<Dynamicweb.Frontend.ItemViewModel> dimensions) GetFacetedContent(ParagraphViewModel model, int maxItems, int pageAreaId, string? tagFilter = null) 59 { 60 var selectedTags = GetSelectedTags(model); 61 62 var contentTypes = model.Item?.GetList("ContentTypes")?.GetRawValue().OfType<string>() ?? Enumerable.Empty<string>(); 63 64 var service = ServiceLocator.Current.GetInstance<INineAContentQueryService>(); 65 var contentWithTags = service.GetContentByTagFilters(pageAreaId, contentTypes, selectedTags, maxItems); 66 67 var availableFilterDimensionPageIds = GetAvailableFilterDimensionPageIds(service, contentWithTags, pageAreaId); 68 var dimensions = GetPagesByPageId(availableFilterDimensionPageIds); 69 70 if (tagFilter != null) 71 { 72 contentWithTags = 73 contentWithTags 74 .Where(x => x.Tags.Any(y => y == tagFilter)) 75 .ToArray(); 76 } 77 78 var localizedTagPageIds = contentWithTags.Select(tag => tag.PageId).Take(maxItems); 79 var content = GetPagesByPageId(localizedTagPageIds); 80 81 return (content, dimensions); 82 } 83 84 private string[] GetSelectedTags(ParagraphViewModel model) 85 { 86 var industry_filters = model.Item?.GetList("Filters_Tags_Industries")?.GetRawValue().OfType<string>(); 87 var vendor_filters = model.Item?.GetList("Filters_Tags_Vendors")?.GetRawValue().OfType<string>(); 88 var domain_filters = model.Item?.GetList("Filters_Tags_Domains")?.GetRawValue().OfType<string>(); 89 var solution_filters = model.Item?.GetList("Filters_Tags_Solutions")?.GetRawValue().OfType<string>(); 90 var product_filters = model.Item?.GetList("Filters_Tags_Products")?.GetRawValue().OfType<string>(); 91 var country_filters = model.Item?.GetList("Filters_Tags_Countries")?.GetRawValue().OfType<string>(); 92 var service_filters = model.Item?.GetList("Filters_Tags_Services")?.GetRawValue().OfType<string>(); 93 var topic_filters = model.Item?.GetList("Filters_Tags_Topics")?.GetRawValue().OfType<string>(); 94 95 var allTags = (industry_filters ?? []) 96 .Concat(vendor_filters ?? []) 97 .Concat(domain_filters ?? []) 98 .Concat(solution_filters ?? []) 99 .Concat(product_filters ?? []) 100 .Concat(country_filters ?? []) 101 .Concat(service_filters ?? []) 102 .Concat(topic_filters ?? []) 103 .ToArray(); 104 105 return allTags; 106 } 107 108 private IEnumerable<int> GetAvailableFilterDimensionPageIds(INineAContentQueryService service, INineATaggedContent[] contentWithTags, int pageAreaId) 109 { 110 var interactiveFilter = Model.Item?.GetString("Filter_Interactive_Tag_Dimension"); 111 112 if (string.IsNullOrWhiteSpace(interactiveFilter)) 113 return []; 114 115 var interactiveFilterDimension = NineATag.FromPrefix(interactiveFilter); 116 if (interactiveFilterDimension == null) 117 return []; 118 119 var dimensionsTagIds = contentWithTags.GetUsedTagsWith(interactiveFilterDimension); 120 if (!dimensionsTagIds.Any()) 121 return []; 122 123 var tagContent = service.GetContentByTagIds(pageAreaId, dimensionsTagIds, contentWithTags.Length); 124 var localizedTagPageIds = tagContent.Select(tag => tag.PageId); 125 126 return localizedTagPageIds; 127 } 128 129 private List<Dynamicweb.Frontend.ItemViewModel> GetPagesByPageId(IEnumerable<int> pageIds) 130 { 131 var lists = new List<Dynamicweb.Frontend.ItemViewModel>(); 132 133 if (pageIds.Any()) 134 { 135 foreach (var tagPageID in pageIds) 136 { 137 var page = Dynamicweb.Content.Services.Pages?.GetPage(Dynamicweb.Core.Converter.ToInt32(tagPageID)) ?? null; 138 var viewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(page)?.Item ?? null; 139 140 if (viewModel != null) 141 { 142 lists.Add(viewModel); 143 } 144 } 145 } 146 return lists; 147 148 } 149 } 150 151 <div class="item_@Model.Item.SystemName.ToLower() @theme @contentPadding"> 152 @if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 153 { 154 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "h2"); 155 string headingLevel = Model.Item.GetString("HeadingLevel", "h2"); 156 string headingLevelStart = $"<{headingLevel} class=\"{titleFontSize} mb-4\" id=\"gates_{@Model.PageID}\">"; 157 string headingLevelStop = $"</{headingLevel}>"; 158 159 @headingLevelStart 160 @Model.Item.GetString("Title") 161 @headingLevelStop 162 } 163 164 <div class="d-flex gap-1 gap-sm-3 my-3 flex-wrap "> 165 @if (dimensions != null) 166 { 167 var relativeUri = Dynamicweb.Context.Current.Request.RawUrl; 168 var host = Dynamicweb.Context.Current.Request.Url.Host; 169 if (host.Contains("localhost")) 170 { 171 host = host + ":" + Dynamicweb.Context.Current.Request.Url.Port; 172 } 173 174 var newUri = new Uri(Dynamicweb.Context.Current.Request.Url, relativeUri); 175 176 @foreach (var category in dimensions) 177 { 178 var tagId = category.GetString("tag_id"); 179 var curRef = $"{newUri.Scheme}://{host}{newUri.AbsolutePath}"; 180 var link = $"{curRef}?filter={tagId}#gates_{Model.PageID}"; 181 182 183 string isActive = filter == tagId ? "active " : ""; 184 string isActiveBtnType=filter == tagId ? "btn-secondary":"btn-primary"; 185 <div> 186 <a class="btn @isActiveBtnType @buttonSize @buttonShape @isActive text-nowrap" href="@link"> @category.GetString("Title")</a> 187 </div> 188 } 189 190 @if (!string.IsNullOrEmpty(filter)) 191 { 192 var curRef = $"{newUri.Scheme}://{host}{newUri.AbsolutePath}"; 193 var link = $"{curRef}#gates_{Model.PageID}"; 194 195 <div> 196 <a class="btn btn-link @buttonSize @buttonShape" href="@link" style="padding-block: var(--swift-button-primary-padding-y);"> @Translate("Clear Filter")</a> 197 </div> 198 } 199 200 } 201 @if (Model.Item.GetBoolean("Show_GoTo_Button")) 202 { 203 var gotoButtonText = Model.Item.GetString("GoTo_Button_Text"); 204 var link = Model.Item.GetString("GoTo_Link"); 205 206 @if (!string.IsNullOrEmpty(gotoButtonText) && !string.IsNullOrEmpty(link)) 207 { 208 <a href="@link" class="btn btn-link ms-auto @buttonSize @buttonShape" style="padding-block: var(--swift-button-primary-padding-y);">@gotoButtonText</a> 209 } 210 } 211 212 </div> 213 214 215 <div class="grid g-col-12" style="background-color:transparent"> 216 @{ 217 int itemCount = 0; 218 } 219 @foreach (ItemViewModel item in content) 220 { 221 itemCount++; 222 223 //if the there are 5 or 7 items, the first item should fill up more space 224 @if (itemCount==1 && gridShouldBeSplit) 225 { 226 @:<div class="g-col-12 g-col-lg-4"> 227 } 228 229 // If there are 5 or 7 items, the rest of the items should be in a seperate grid. 230 @if ((itemCount==2 && gridShouldBeSplit)) 231 { 232 @:<div class="@secondChildOfGridCSS"> 233 } 234 235 // All items that are not the first one, in case case there are 5 or 7 items, should have their own classes. 236 //Or if there aren't 5 or 7 items, then all should have this css 237 @if ((itemCount!=1 && gridShouldBeSplit) || !gridShouldBeSplit) 238 { 239 240 @:<div class="@secondChildOfGridChildCSS"> 241 242 } 243 244 <article class="card h-100 border-0 @cardTheme @cardShapeCSS overflow-hidden shadow-hover" itemscope="" itemtype="https://schema.org/CreativeWork" style="background-color: var(--swift-background-color)"> 245 246 @if (!String.IsNullOrEmpty(item.GetString("Image"))) 247 { 248 <a class="position-relative" title="@item.GetString("Title")" href="@item.Link" tabindex="-1"> 249 <figure class="overflow-hidden m-0 mx-auto @ratioCssClass" @ratioVariable> 250 @{ 251 var coverImagePath = Dynamicweb.Context.Current.Server.UrlEncode(item.GetString("Image")); 252 string image = item.GetString("Image"); 253 254 string coverImagePathM = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=640&format=webp"; 255 string coverImagePathL = $"/Admin/Public/GetImage.ashx?image={coverImagePath}&width=960&format=webp"; 256 string imagePathFallBack = coverImagePathM; 257 258 <img srcset=" 259 @coverImagePathM 640w, 260 @coverImagePathL 960w" 261 src="@imagePathFallBack" 262 sizes="(min-width: 992px) 25vw, 100vw" 263 loading="lazy" 264 decoding="async" 265 class="img-fluid image-zoom-lg-1-hover" 266 style="object-fit:cover; object-position: 50% 50%;" 267 alt="@item.GetString("Title")"> 268 } 269 </figure> 270 </a> 271 } 272 273 <div class="col d-flex flex-column p-3"> 274 <div class="card-body p-0 d-flex flex-column gap-2"> 275 <a class="text-decoration-none text-decoration-underline-hover" href="@item.Link"> 276 <h3 class="@cardTitleSize mb-0" itemprop="headline"> @item.GetString("Title")</h3> 277 </a> 278 279 @if (!String.IsNullOrEmpty(item.GetRawValueString("Summary"))) 280 { 281 <p class="m-0 opacity-75">@item.GetRawValueString("Summary")</p> 282 } 283 284 @if (!String.IsNullOrWhiteSpace(cardButtonText)) 285 { 286 <div class="mt-auto"> 287 <a href="@item.Link" class="btn @cardButtonStyle @cardButtonSize lh-1 text-start"> 288 289 @if (showCardButtonIcon) 290 { 291 <span class="icon-auto"> 292 @ReadFile(iconPath + "arrow-right.svg") 293 </span> 294 } 295 296 @if (showCardButtonText) 297 { 298 <span>@cardButtonText</span> 299 } 300 </a> 301 </div> 302 } 303 </div> 304 305 <div class="card-footer p-0 pt-3 border-top-0"> 306 <div class="d-flex align-items-center justify-content-between gap-3"> 307 308 @if (!String.IsNullOrEmpty(item.GetString("PublishedDate")) && item.GetDateTime("PublishedDate").Year != 1900 && item.GetDateTime("PublishedDate") != DateTime.MinValue) 309 { 310 string articleDateTime = item.GetDateTime("PublishedDate").Year + "-" + 311 item.GetDateTime("PublishedDate").Month + "-" + item.GetDateTime("PublishedDate").Day; 312 string publishedDate = item.GetDateTime("PublishedDate").ToShortDateString(); 313 314 <div class="d-flex align-items-center gap-1 fs-8 opacity-75"> 315 <div class="icon-1"> 316 @ReadFile(iconPath + "calendar.svg") 317 </div> 318 <time datetime="@articleDateTime" itemprop="datePublished">@publishedDate</time> 319 </div> 320 } 321 </div> 322 </div> 323 </div> 324 </article> 325 326 @if ((itemCount!=1 && gridShouldBeSplit) || !gridShouldBeSplit) 327 { 328 @:</div> 329 } 330 @if ((itemCount==content.Count && gridShouldBeSplit)) 331 { 332 @:</div> 333 } 334 @if (itemCount==1 && gridShouldBeSplit) 335 { 336 @:</div> 337 } 338 } 339 </div> 340 </div> 341

Pricing: What to expect for your business?

Our job is to simplify your journey to the summit, ensuring a smoother climb to new heights where you continuously feel safeguarded and in control. That's exactly why we've made it possible for you to obtain a high-level budget estimation already.

How? By completing this guiding questionnaire, we can estimate the project implementation investment and the monthly Microsoft license estimate, based on our experience in implementing many projects like the one you envision.

9altitudes as your service partner

9altitudes as your service partner

9altitudes is an international digital partner that automates, optimizes and continuously improves business processes end-to-end. We help manufacturing, supply and service companies reach new heights using Microsoft, PTC and Tulip software in combination with our own industry-specific solutions.

With employees from 9 different countries, our team consists of 750 exceptionally talented experts. Our digital advisors are tireless in their pursuit of innovation, dedicated to creating exceptional customer experiences and delivering impactful solutions for your better tomorrow.

Get in touch

If you want to learn more about Microsoft Dynamics 365 Field Service or need assistance, our team is here to help. Get in touch today and let’s discuss how we can support your business growth.

Get in touch