简体   繁体   中英

ASP.NET MVC 5.1 EditorFor and DisplayFor not Using Custom Templates

suddenly my MVC application stopped using the custom EditorFor or DisplayFor templates I have. I'm not sure when exactly it failed since I've been changing the UI. I have the templates sitting in DisplayTemplates and EditorTemplates under the Shared folder. I do override the ViewEnginesCollection in Global.asax with this:

ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CSHtmlRazorViewEngine {
    PartialViewLocationFormats = new string[] { 
        "~/Views/Shared/EditorTemplates/{0}.cshtml",
        "~/Views/Shared/Partials/{0}.cshtml"
    }
});

Where CSHtmlRazorViewEngine is:

public sealed class CSHtmlRazorViewEngine : RazorViewEngine {
    public CSHtmlRazorViewEngine()
        : base() {
        this.AreaViewLocationFormats = new string[2] {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml"
        };
        this.AreaMasterLocationFormats = new string[2] {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml"
        };
        this.AreaPartialViewLocationFormats = new string[2] {
            "~/Areas/{2}/Views/{1}/{0}.cshtml",
            "~/Areas/{2}/Views/Shared/{0}.cshtml"
        };
        this.ViewLocationFormats = new string[3] {
            "~/Views/{0}.cshtml",
            "~/Views/{1}/{0}.cshtml",
            "~/Views/Shared/{0}.cshtml"
        };
        this.MasterLocationFormats = new string[2] {
            "~/Views/{1}/{0}.cshtml",
            "~/Views/Shared/{0}.cshtml"
        };
        this.PartialViewLocationFormats = new string[2] {
            "~/Views/{1}/{0}.cshtml",
            "~/Views/Shared/{0}.cshtml"
        };
        this.FileExtensions = new string[1] {
            "cshtml"
        };
    }
}

I'm having a bit of a hard time understanding where I've gone wrong all of the sudden. Any recommendations on where to check for what?

UPDATE - Code Examples

Here's the Edit.cshtml page for an Office object:

<div class="Section">
    @using (Html.BeginForm("Edit", "Offices", new {
        id = Model.Office.Id
    }, FormMethod.Post)) {
        <div>
            <input type="submit" value="Save" />
        </div>
        @Html.EditorFor(m => m.Office, new {
            Regions = Model.Regions,
            States = Model.States
        })
    }
    @Html.Partial("Equipments", Model.Equipments)
</div>

And here's the EditorFor template for Office that's being requested:

@model Office
<p>
    @Html.Label("Name", "Name:")
    @Html.TextBox("Name", Model.Name, new {
        required = string.Empty
    })
</p>
<p>
    @Html.Label("RegionId", "Region:")
    @Html.DropDownList("RegionId", new SelectList((IEnumerable<Region>)ViewData["Regions"], "Id", "Name", Model.RegionId), string.Empty, new {
        required = string.Empty
    })
</p>
@Html.EditorFor(m => m.Address)

And here's the OfficesController.Edit() ActionResult :

[HttpGet]
public async Task<ActionResult> Edit(
    short id) {
    if (id > 0) {
        Office office = await base.Repository.FindSingleOrDefaultAsync<Office, short>(id);

        if (office != null) {
            Task<IQueryable<Equipment>> equipments = Task.Run(() => base.Repository.FindEquipment<Office>(id));
            Task<IQueryable<Region>> regions = Task.Run(() => base.Repository.Find<Region>());
            Task<IQueryable<State>> states = Task.Run(() => base.Repository.Find<State>());

            await Task.WhenAll(equipments, regions, states);

            return base.View(new OfficesView {
                Equipments = equipments.Result.ToList(),
                Office = office,
                Regions = regions.Result,
                States = states.Result,
                ViewData = new OfficeViewData {
                    Map = new Map {
                        Center = office.Address.Position.ToPoint(),
                        Polygons = (office.Boundaries != null) ? new Polygon[] {
                            office.Boundaries.ToPolygon()
                        } : null
                    }
                }
            });
        }
    }

    return base.RedirectToAction("List");
}

There are no compilation or run-time exceptions being generated. The EditorFor just silently fails to find the template and generates the default one instead. The code pattern pretty much repeats for every other object.

MVC will add itself the EditorTemplates/ segment to the partial view name when looking for an editor template. You can check the source code here , ExecuteTemplate function.

You have set the partial view locations as:

"~/Views/Shared/EditorTemplates/{0}.cshtml"
"~/Views/Shared/Partials/{0}.cshtml"

When looking for the Address editor template, MVC will use EditorTemplates/Address as the partial view name. That means it will check the 2 following partial view locations:

~/Views/Shared/EditorTemplates/EditorTemplates/Address.cshtml
~/Views/Shared/Partials/EditorTemplates/Address.cshtml

If it cannot find them there, it will go back the default editor templates.

Probably your editor templates are sitting currently in the first EditorTemplates folder?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM