2013-09-24 106 views
2

所以,我試圖找到Umbraco節點(如iPublishedContent),並將其傳遞給viewModel(如Ш've劫持了一條路線)。所以我把這個在我的控制器:System.NullReferenceException創建視圖模型

private AddCouponCodesViewModel viewModel; 
public AddCouponCodesController(){ 
    //Get iPublished content 
    IPublishedContent content = Umbraco.TypedContent(1225); 
    //Pass to viewModel 
    viewModel = new AddCouponCodesViewModel(content); 
    RouteData.DataTokens["umbraco"] = content; 
} 
public ActionResult Index() 
{ 
    //return view etc 
} 

但是我卻越來越

Exception Details: System.NullReferenceException: 
Object reference not set to an instance of an object. 

這裏:

Source Error(AddCouponCodesViewModel.cs): 
Line 20: 
Line 21:   } 
Line 22:   public AddCouponCodesViewModel(IPublishedContent content) 
Line 23:    : base(content) 
Line 24:   { 

AddCouponCodeRenderModel.cs:

public class AddCouponCodesViewModel : RenderModel 
    { 
    public string test { get; set; } 
    public List<string> tables { get; set; } 
    public List<string> errors { get; set; } 

    public AddCouponCodesViewModel(IPublishedContent content, CultureInfo culture) : base(content, culture) 
    { 

    } 
    public AddCouponCodesViewModel(IPublishedContent content) 
     : base(content) 
    { 

    } 

這是Global.asax

public class Global : UmbracoApplication 
{ 
    protected override void OnApplicationStarted(object sender, EventArgs e) 
    { 
     base.OnApplicationStarted(sender, e); 

     BundleConfig.RegisterBundles(BundleTable.Bundles); 
     //AreaRegistration.RegisterAllAreas(); 
     //WebApiConfig.Register(GlobalConfiguration.Configuration); 
     //FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
     //RouteConfig.RegisterRoutes(RouteTable.Routes); 

     base.OnApplicationStarting(sender, e); 

     RouteTable.Routes.MapRoute(
     "AddCouponCodes",            // Route name 
     "Admin/{controller}/{action}/{id}",       // URL with parameters 
     new { controller = "AddCouponCodes", action = "Index", id = "" } // Parameter defaults 
     ); 


    } 

} 

內容發佈(我查和雙重檢查),節點ID是正確的。

我基本上試圖在這裏做的是獲取路線example.com/Admin/{controller}/{action}/{parameter} 路由,但有問題連接它與umbracoNode(和類RenderModel需要iPublishContent對象作爲參數,而是試圖通過它的任何東西)

可能有人請幫助我在這裏的時候,我在沒有運氣,一直停留太多的時間在這個:-(

+0

您應該顯示「RenderModel」類的代碼。根據你說錯誤發生的地方,它看起來像是在該類的構造函數中發生錯誤。 –

回答

0

那麼,我可以告訴你,你的觀點並沒有爲Razor標記提供任何東西,因爲你的Index方法並沒有給它提供任何東西,這是一個問題,我還可以告訴你,在你的AddCouponCodesViewModel中,你會需要一個空的構造函數,以便剃刀語法可以創建一個實例,然後填充它以將提交的對象與視圖相匹配。

修改您的視圖控制器:

public ActionResult Index() 
    { 
     return View(viewModel); 
    } 

修改您的AddCouponCodesViewModel添加一個空的構造:

public AddCouponCodesViewModel() 
{ 
} 
+0

編譯器默認生成一個空構造函數,所以自己創建一個是多餘的。 –

+0

^那和RenderModel(一個umbraco類(?))不能有無參數的構造函數。 – user994059

+0

@HenkMollema看看上面。一旦你創建了一個構造函數,它就不再生成一個空的。就像一個人站起來一樣。 –

0

您的視圖模型創建paramaterless構造是這樣的:

public AddCouponCodesViewModel(): 
    this(new UmbracoHelper(UmbracoContext.Current). 
TypedContent(UmbracoContext.Current.PageId)) 
    { 
    } 

這將獲得您的其他構造函數正在尋找的上下文。 創建具有特定構造函數的類後,編譯器將默認停止生成無參數類。因爲你需要一個無參數的構造函數,所以這是如何得到一個,仍然通過你的視圖模型需要的Umbraco上下文信息

+0

我必須包含什麼才能獲得UmbracoHelper和UmbracoContext?無法找到關於類的任何文檔,所以我不知道要導入什麼。試過Umbraco.Web.UmbracoHelper和Umbraco.Web。UmbracoContext,Visual查找類,但仍然出現錯誤,它不在當前上下文中(對不起,這裏有一些愚蠢的問題) – user994059

+0

@Duncanmhor你不能這樣做,因爲你不在Umbraco上下文中,所以'UmbracoContext.Current '將爲空。這也是一個不好的方法,因爲a)如果你有權訪問'UmbracoContext',那麼永遠不需要創建一個新的'UmbracoHelper'。這只是不必要的代碼重複,b)您將潛在的異常引入到應該始終避免的構造函數中,以及c)當Umbraco團隊中的好人遇到了麻煩時,您正在將具體實例推入構造函數參數中儘可能使事物鬆散耦合。 – Digbyswift

1

爲了澄清,如果你劫持一條路線,這意味着你重寫了Umbraco通過它的方式RenderModel到其發佈的頁面之一。您可以通過覆蓋主要的RenderMvcController來在全局範圍內執行此操作,也可以根據具體情況重寫DocumentType。因此,舉例來說,如果我有一個網頁的文檔類型,我可以創建:

public HomepageController : RenderMvcController 
{ 
    public override ActionResult Index(RenderModel model) 
    { 
     // Create your new renderModel here, inheriting 
     // from RenderModel 

     return CurrentTemplate(renderModel); 
    } 
} 

這將路線主頁所有調用都通過這一個動作。爲此,您不需要需要在路由表中定義任何新的路由。並且您應該覆蓋動作中的渲染模型,而不是在構造函數中。

你的問題是略顯混亂,它不是完全清楚你正在努力實現的原因是什麼:

  • 您已經定義的路由,並
  • 在你的構造您所呼叫Umbraco.TypedContent(1225)檢索特定的出版節點

所以...如果你想路由管理頁面本身已經被出版一把umbraco(和它聽起來並不像它),剛剛創建一個新的控制器與頁面的名稱文件按照上述方式鍵入並覆蓋渲染模型。

但是...如果你的管理頁面還沒有被公佈一把umbraco,你只是想管理頁面訪問節點的數據,那麼你有兩個選擇:

  • 創建地面控制器,從SurfaceController繼承。這將使您能夠訪問Umbraco context等;或
  • 創建一個標準控制器(最好是在一個地區)和使用類似Autofac注入ContentCache

例如:

builder.RegisterControllers(typeof (AdminController).Assembly) 
     .WithParameter("contentCache", UmbracoContext.Current.ContentCache); 
  • 創建一個標準控制器(最好是在一個區)和使用Umbraco的ContentService API訪問節點,即new Umbraco.Core.Services.ContentService().GetById(1225)

最後兩個方法之間的區別在於:

  • 注入ContentCache爲您提供只讀的,但很快進入發佈內容。
  • 訪問ContentService爲您提供對節點本身的讀/寫訪問權限,但是會在您直接查詢數據庫時以犧牲速度爲代價。

這取決於您的要求是什麼。

無論哪種方式,花費時間閱讀documentation for hijacking Umbraco routes,至少試圖瞭解發生了什麼。

+0

是的,我有一個umbraco節點,並不是我真的需要它。剛進入umbraco/MVC,它有點混亂,但我開始掌握它。非常感謝您的詳細解答:-) – user994059

+0

爲了說明問題,我在/ Admin中有我的adminpanel,並希望將各種控制器(管理員操作)映射到Admin/{Controller}/{action},最好使用匹配的umbraco節點,因爲我以後可能會使用它們。 – user994059

+0

但是你的「管理面板」由Umbraco發佈嗎?如果是這樣,那麼你需要劫持我描述的路線。如果管理面板不是由Umbraco發佈的,但實際上您只是想要訪問管理面板中的Umbraco節點,那麼您*不希望'劫持'這些路由。你只需要訪問Umbraco的ContentCache。如果你不想使用注入,你可以通過API使用新的Umbraco.Core.Services.ContentService()。GetById(1225)來訪問'ContentService'。詳情請看這裏:http://our.umbraco.org/documentation/Reference/Management-v6/Models/Content – Digbyswift