3

Kürzlich Dotnet Kern 1.0.1 bis 1.1 aktualisiert und ViewComponent in MVC mit der folgenden Ausnahme beginnt versagt:InvalidOperationException ViewComponent Rendering in stark typisierte Ansicht

InvalidOperationException: One or more errors occurred. (The model item passed into the ViewDataDictionary is of type 'App.Models.HomeViewModel', but this ViewDataDictionary instance requires a model item of type 'App.Components.LoginViewComponent'.) 

Die Index.cshtml macht LoginViewComponent:

@model App.Models.HomeViewModel 
<html> 
    @Component.InvokeAsync("LoginViewComponent") 
</html> 

Ansichten/Home/Index.cshtml

Die ViewComponent LoginViewComponent/Default.cshtml ist nur eine Klasse, die Informationen, es ist das Modell zeigt:

@model App.Components.LoginViewCompoent 
<body> 
    <div>@Html.DisplayFor(v=>v.LoginName)</div> 
</body> 

Views/Shared/Komponenten/LoginViewComponent/Default.cshtml

Es macht in Ordnung, wenn Die @model Direktiven wurden entfernt von Default.cshtml.

Darf ViewComponent nicht von der übergeordneten Ansicht, die es einhüllt, getrennt und agnostisch sein? Von der Ausnahme scheint es erforderlich zu sein, die LoginViewComponent ViewComponent in HomeViewModel Klasse zu deklarieren, um es zu rendern.

Konnte keinen Änderungshinweis auf diesem asp.net Core Github finden.

Kommentar und Hilfe zu diesem würde sehr geschätzt werden.

+0

haben Sie udpate Abhängigkeiten auch? (mvc 1.1.0 etc ...) –

+0

@agua von mars Yup, alle _Microsoft.AspNetCore. * Referenz _ ist auf Version 1.1.0 – danial

+0

sieht das komisch zu mir: '@model App.Components.LoginViewCompoent', ist es ein Modell oder eine Komponente? –

Antwort

4

Ich habe kam über den gleichen Fehler, jemand in meinem Team aktualisiert Microsoft.AspNetCore.Mvc Version von 1.0.0 bis 1.1.0 und einige der Komponenten hatte ich in Stark-Typ Ansichten begann werfen

InvalidOperationException: Das in das ViewDataDictionary übergebene Modellelement hat den Typ 'My.StronglyView.ObjectType', aber diese ViewDataDictionary-Instanz erfordert ein Modellelement vom Typ 'My.ViewComponent.ObjectType'.

Ich bin nicht sicher, ob diese Änderung absichtlich war, aber es ist definitiv nicht das, was wir erwarten würden.

Ich habe nicht die Zeit, um über die Gründe dieser "brechenden" Änderung zu recherchieren, aber ich kam mit einer Lösung.

Die Sache ist, wenn Sie ein Null-Objekt an Ihre ViewComponent.View() Methode übergeben, erhalten wir diese Ausnahme. Jedes Nicht-Null-Objekt, das durch es übergeben wurde, würde die ViewData aktualisieren.ModelExplorer und der korrekte Objekttyp wären registriert worden, um diese Ausnahme zu vermeiden.

Mithilfe von Tester-Doer-Muster, das gleiche Muster in einigen Klassen von .Net-Framework verwendet, können wir nun ein Nicht-Null-Objekt an die ViewComponent übergeben und es und sein umgebendes Objekt verwenden, wie wir brauchen.

Was ich tat, war, habe ich eine Schnittstelle IViewComponentModel<T> als Klasse ViewComponentModel<T> wie folgt:

// Interface for ViewComponentModel 
public interface IViewComponentModel<T> 
    where T : class 
{ 
    T Data { get; } 
    bool HasData(); 
} 

// ViewComponentModel class for the Strongly-Type View Component 
public class ViewComponentModel<T> : IViewComponentModel<T> 
    where T : class 
{ 
    public T Data { get; private set; } 

    public ViewComponentModel(T data) 
    { 
     Data = data; 
    } 

    public bool HasData() => Data != null; 
} 

In meiner ViewComponent Klassenimplementierung, kehre ich View(new ViewComponentModel<AnyReferenceType>(myModel));

public async Task<IViewComponentResult> InvokeAsync() 
{ 
    var myViewData = _myService.GetSomeObjectForMyViewComponent(); 
    var model = new ViewComponentModel<MyViewDataType>(myViewData); 

    return await Task.FromResult(View(model)); 
} 

Und schließlich in meinem Component View (.cshtml) Ich habe den folgenden Code:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 
@model ViewComponentModel<MyViewDataType> 

Jetzt können Sie tun, was Sie wollen mit diesem Objekt innerhalb der Ansicht und Ihr echtes Modell verwenden, rufen Sie einfach @Model.Data und voilà.

Auf diese Weise übergeben wir niemals ein Null-Objekt an die ViewComponent und es wird den Objekttyp nicht von der Ansicht "erben".

Hoffentlich hilft es!

+0

Ja .. konnte keine Informationen auf den Versionshinweisen finden. aber cool .. ich werde es ausprobieren. Danke Alex – danial

0

Standardmäßig wird es versuchen, in dem Modell des „Parent View“ passieren, nicht sicher, was Sie so nennen würden, versuchen Sie Ihren Code wie diese

@Component.InvokeAsync("LoginViewComponent", new App.Components.LoginViewComponent()) 

so dass Teilansicht aktualisieren kann, was haben sie braucht, um seinen Inhalt zu erfüllen.

+0

Hmm, das hat nicht funktioniert, aber ich denke, die Problemumgehung besteht darin, eine instanziierte ViewModel-Instanz über die ViewComponent InvokeAsync-Methode zu übergeben. Danke, obwohl – danial

0

einfache Lösung besteht darin, dass in ViewComponent Klasse Prüfung null für View-Modell, und wenn View-Modell null ist, dann leer Inhalt Ergebnis zurück, wie folgend:

public async Task<IViewComponentResult> InvokeAsync() 
{ 
    var vm = some query for ViewModel; 

    if(vm != null) 
    { 
     return View(vm); 
    } 

    return Content(""); 
} 
Verwandte Themen