低碳趨勢無法擋,石油巨擘殼牌進軍歐洲EV充電市場

 

荷蘭皇家殼牌(Royal Dutch Shell plc)10月12日宣布收購電動車(EV)充電服務經營商NewMotion。依據收購條件、NewMotion將成為殼牌旗下全資子公司。

殼牌新聞稿顯示,NewMotion在英國、法國、德國以及荷蘭經營超過3萬個私人(包括家庭、企業)電動車充電點。此外,NewMotion在歐洲25個國家擁有超過5萬個公共充電點、對逾10萬張註冊充電卡提供服務。

NewMotion表示,這項收購案將可協助公司提升EV充電服務、將更多的停車空間改裝成充電站,進而提升歐洲使用者的充電體驗。

(本文內容由授權使用。圖片出處:)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

※推薦評價好的iphone維修中心

布局新能源,石油大廠殼牌開始在自家加油站推出充電服務

  石油大廠荷蘭皇家殼牌(Shell)近日宣布,將在英國北部 10 個地方開始提供電動車的快速充電服務。   英國獨立報報導,殼牌提供的這項快速充電服務,能讓多數電動車的電量在半小時內從零充飽到 80%,這也是殼牌首次正式設置電動車充電站。   許多跡象都顯示,石油公司已經開始意識到「充電」業務對下游業務部分造成的一些威脅。不只是殼牌,競爭對手英國石油公司 BP 在 8 月時也曾談到正在與電動車商討論合作,計劃一同在零售場所提供充電站服務。   不久之前,殼牌才剛宣布收購歐洲最大電動車充電網路之一的 NewMotion,對於持續往電動車發展的傾向,未來燃料經理 Jane Lindsay-Green表示,這是因為殼牌認為,電動車將成為未來運輸網路中非常重要的一部分。   NewMotion 在歐洲約設有 5 萬個公共充電站,雖然殼牌這次設置的規模遠小於 NewMotion 的業務,但這次的服務是殼牌首次在自家的加油站內,提供了汽油和柴油以外的充電選擇。   隨著消費者對電動車需求的增長,殼牌未來將會在英國進一步擴大服務,甚至有計劃擴大至荷蘭和菲律賓地區。殼牌預計至 2040 年,全球將有約四分之一的汽車會有充電需求。   目前已經在路上行駛的電動車還不到 10 萬輛,但隨著使用人數持續增加,摩根史丹利(Morgan Stanley)估計,至 2030 年時,光是西歐可能就需要 100~300 萬個公共充電站才能滿足電動車的需求。   Lindsay-Green 表示,殼牌預計將在 2018 年時,對於客戶的需求開始進行正式調查,「對於殼牌來說,這是一個全新的領域,我們需要探索不同的機會…我們會先從小地方著手,並且開始快速學習。」   (合作媒體:。首圖來源:)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

中國車廠挺禁售燃油車政策研究,有助新能源車加快發展

證券日報報導,中國工信部副部長辛國斌於今年9月初透露,工信部已啟動停止生產銷售傳統燃油汽車時間表的研究。靠研發生產電池起家的中國民營車企比亞迪董事長王傳福預測,中國2030年起將禁售傳統燃油汽車。而已在中國傳統燃油車做到自主品牌第一的長安汽車總裁朱華榮,更喊出2025年長安汽車將開始全面停止銷售傳統意義的燃油車,實現全系列產品的電氣化的目標。   據了解,德國宣布到2030年、法國宣布到2040年、英國宣布到2040年將禁止銷售傳統柴油車和汽油車,印度也宣布2030年要淘汰全部汽油車和柴油車。如果按照長安汽車2025年停售燃油車的時間表在中國全國執行,則中國將是第一個禁售傳統燃油車的國家。   對於長安汽車所提出的2025年停售傳統燃油車,市場分析,這可能與中國電動汽車百人會理事長陳清泰於9月下旬舉辦的中國電動汽車百人會常州論壇上表態有關,當時陳清泰提到,「最遲到2025年,電動汽車的性價比將達到或超過傳統燃油車」。   陳清泰的表態比王傳福2030年禁售傳統燃油車的表態晚了三天,但卻比王傳福更有分量,因為中國電動汽車百人會是一個與中國政府有著親密關係的非官方機構,機構顧問委員會有一批在職高官,例如科技部部長萬鋼、工信部部長苗圩。陳清泰非官方的表態可能接近中國官方接下來公布的停止生產銷售傳統燃油汽車的時間。   而中國在發展電動汽車方面,隨著政府後期出臺的新能源汽車補貼政策,目前中國新能源汽車市場幾乎被享受優惠政策的自主品牌車企壟斷;加上2018年至2019年「雙積分(車企油耗積分+新能源汽車積分)」制度的展開,中國車企在內有市場、外有政策支持的情況下,可能相較歐美國家先一步步入全面電動汽車時代。   (本文內容由授權使用。首圖來源:public domain CC0)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

欲練神功必先自宮?國際石油巨擘加強投資電動車、綠能

對石油巨擘來說,最大的心腹之患,就是未來電動車若普及,最大宗石油需求之一:內燃機車輛用的汽柴油,就會大幅萎縮,其次則是終有一日可再生能源發展到不只可取代煤,還能取代燃氣發電,往往與石油一併產出的天然氣也不知該何處去了。依此觀點,油氣大廠應該全面抵制電動車與綠能,不過,資本家想的不一樣,不管是出於避險,或是「打不贏就加入」,國際油氣大廠殼牌、道達爾大力投資電動車、綠能。 電動車發展的最大障礙之一就是充電站不夠普及,而石油巨擘殼牌(Shell)不旦不針對這點打擊潛在對手,還「贈敵予鹽」出手相助。2017 年 10 月 13 日,殼牌宣布購併電動車充電站企業 NewMotion,NewMotion 身為歐洲最大電動車充電網路之一,旗下管理 3 萬座住宅與商業充電站,加上其他結盟充電站系統,並可提供車主使用 5 萬座以上充電站。 殼牌會不會採取是「買下後拋棄」策略,購併關鍵環節後,藉由故意拖慢其發展,打算藉此拖累電動車的普及進度?就殼牌的動作來說,看來並不像,因為殼牌不僅大動作投資 NewMotion,更實際推動充電站數量增加,在殼牌加油站本身就提供電動車快速充電服務,可於 30 分鐘內充電 80%。殼牌此計畫預定將從英國北部開始,從英國 400 座殼牌加油站先挑選 10 座測試。除了支援電動車的充電站,殼牌還將於 2017 年內於英國 3 個所屬加油站設立氫燃料電池車的加氫站。

(Source:Flickr/Mike Mozart CC BY 2.0) 事實上殼牌並非突發奇想,投資綠能早已是殼牌的長期策略。殼牌目前每年投資 2 億美元在可再生能源,更計畫到 2020 年時提升到 10 億美元;推動電動車充電站的計畫也不僅在英國,還包括挪威、菲律賓、荷蘭。殼牌積極跨足電動車可說是未雨綢繆,根據殼牌自身估算,2040 年全球將有四分之一汽車為電動車,在傳統汽車市佔不可避免逐漸受侵蝕的情況下,殼牌當然得先在電動車領域建立灘頭堡。 法國石油巨擘道達爾的看法也英雄所見略同。道達爾估計至 2030 年時電動車將佔有新車市場 15%~30%,石油需求預計屆時將達頂峰,之後不再成長甚至逐漸下滑。艾克森美孚(ExxonMobil)、英國石油(BP)則分別預期到 2035 年、2040 年,全球電動車總數量就會超過 1 億輛。 因此,殼牌買下 NewMotion,道達爾也出手買下兼營天然氣與電動車充電的 PitPoint,殼牌也與道達爾共同參與全球氫能會議未來 5 年對氫能 107 億美元的投資。殼牌也擁有 400 百萬瓦(megawatt)規模的風力發電場。英國石油則在美國擁有 1.5 吉瓦(gigawatt)風力發電容量。挪威國家石油公司(Statoil)則計劃將於 2018 年為蘇格蘭 Hywind 漂浮式離岸風電計畫添加 1,000 度電儲能容量的鋰電池能源儲存系統。

(Source:statoil) 除此之外,道達爾先前 2017 年 9 月大舉投資法國 EREN 集團可再生能源部門(EREN RE),以 2.375 億歐元買下 23% 股權,以及 5 年內可買下剩下所有股權的選擇權。EREN 可再生能源部門將改名為「道達爾 EREN」,道達爾表示希望此投資能大幅加速道達爾打進太陽能與風能市場的速度;同月,道達爾也買下法國節能公司 GreenFlex。 道達爾先前已宣布 2035 年前將投資五分之一資產配置於可再生能源,先前就已積極投資,2011 年注資 14 億美元投資美國晶矽太陽能電池龍頭太陽能源(SunPower),到 2017 年並設立道達爾太陽能部門,打算發展商用及工業等級太陽能發電場;2016 年時,道達爾斥資 11 億美元買下生產鎳氫、鎳鎘與一次性鋰電池的法國電池廠 Saft,道達爾風險創投部門則投資美國風機租賃業者聯合風能(United Wind)。 比起其他同業,艾克森美孚則較鍾情替代燃料。2009 年時宣布注資 6 億美元與合成基因公司(Synthetic Genomics)合作,發展藻類生質燃料,當時艾克森美孚樂觀認為 10 年內就能有所成果,不過如今改為預期要數十年。合成基因以基因科技改造藻類,以提升製造燃料的效率,原本藻類只製造 10%~15% 油脂,這個先天問題讓眾多藻類生質燃料新創企業都遇上困難,但透過基因改造後,2017 年 6 月艾克森美孚與合成基因發表成果,可將藻類製造油脂率拉升到 40%。即使如此,要達到商業可行的規模與成本,還有相當距離。 生質燃料受葉綠素光能轉換率遠低於太陽能電池的基本理論弱點影響,發展遠遜於其他可再生能源,這使艾克森美孚想要靠生質燃料在減碳辯論時保住內燃機汽車的努力可能終究化為泡影。即使最「鐵齒」的艾克森美孚也與電動車有沾到邊,艾克森美孚化學部門早在 2008 年就曾發表生產電動車用電池的薄膜,供應給加拿大電池廠 Electrovaya,用於當年推出的原型電動車 Maya-300。 當前,這些石油巨擘最主要的投資重心仍然還是油氣本業,道達爾最近最大筆投資,是以 75 億美元買下快桅油氣(Maersk Oil & Gas);殼牌每年花在油氣新計畫的預算高達 250 億美元。比起來,雙方對電動車、綠能相關投資,仍是小巫見大巫,這樣的投資規模比例,比較是「避險」性質,還沒有到全盤轉型的程度。

(Source:Ørsted ) 不過,隨著電動車與可再生能源技術日漸成熟,市場接受度也越來越高,或許有一天,會看到過往的石油巨擘,成為電動車或綠能巨擘,一如丹能集團(DONG Energy)原為丹麥石油與天然氣(Danish Oil and Natural Gas)縮寫,積極由傳統能源公司轉型成為綠能公司,並將公司名稱改為沃旭能源(Ørsted )的例子。 (合作媒體:。)

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

※教你寫出一流的銷售文案?

全球首列!中國氫燃料電池有軌電車正式投入營運

  新華社報導,由中國中車唐山公司研製的世界首列商用型氫燃料混合動力100%低地板現代有軌電車,10月26日在河北唐山市唐胥鐵路載客營運,為全球氫燃料電池有軌電車首次商業營運,也是中國在新能源軌道交通領域實現重大突破。   經過4年多時間,中車唐山公司率先在全球首次突破了燃料電池/超級電容混合動力牽引和控制等一系列關鍵技術,研製的有軌電車完全取消受電弓和接觸網,實現污染物「零排放」和全程「無網」運行。   據悉,唐山工業旅遊線路採用氫燃料電池有軌電車,無需架設接觸網,不用沿途安裝第三軌和充電樁,完整保留了百年唐胥鐵路的原貌;列車採用世界最先進的100%低地板技術,車廂地板距軌道面僅35公分,無需月臺;最小轉彎半徑僅19公尺,可沿現有城市道路直接鋪設軌道,在地面行駛和停靠;線路運營全程13.84公里,有軌電車一次快速加氫只需15分鐘,可持續行駛40公里,最高運行時速70公里。   中車唐山公司表示,旗下氫燃料混合動力有軌電車係採用2動1拖3輛編組,設乘客座位66個,最大載客量336人,還可根據運營需求靈活增加編組和載客量;這種有軌電車不僅可最高速度持續運行,且在制動、停站時,由燃料電池和制動能量回收系統為超級電容和蓄電池充電,能量回收率達30%以上。   (本文內容由授權使用。首圖為中車唐山電車示意圖,來源:)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

充電時間縮一半,本田傳2022年開賣多款超快速充電EV

日經新聞1日報導,本田(Honda)計畫在2022年開賣多款可進行「超快速充電」的電動車(EV)、其充電時間可縮短至現行的約一半水準。   現行EV在使用快速充電器時、充飽8成電力大多需花費30分鐘時間,而本田將研發能負荷在短時間內進行大量充電的電池產品,目標將充電時間縮減至15分鐘、且能跑240km。   據報導,本田目前油電混合車(HV)用電池是向Panasonic等廠商採購,而能進行超快速充電的電池研發夥伴將待今後討論決定。   本田目前規畫要在2019年以後於歐洲、日本開賣量產款EV。   (本文內容由授權使用。首圖為本田城市EV概念車,來源:)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

石油需求觸頂是危言聳聽?能源巨擘不怕電動車威脅

  全球環保意識高漲,歐洲和中國相繼宣布,未來將禁售汽柴油車。不少專家預測,石油需求即將觸頂,但是能源巨擘對此嗤之以鼻,深信石油需求將持續成長,對再生能源投資只有石油的九牛一毛。   路透社8日報導,二十年前英國石油公司(BP)看好再生能源,不只改換商標,還宣布要在十年內斥資80億美元發展綠能。不料此一大膽舉動慘敗收場,BP的太陽能事業被陸廠打到無力招架,美國風力發電事業更連賣都賣不掉。BP學到教訓,再次聚焦石油,其他油商也看在眼裡,對於綠能投資格外謹慎。   證據何在?路透訪調分析顯示,全球前五大油商,包括BP、Total、雪佛龍(Chevron)、艾克森美孚(Exxon Mobil)、荷蘭殼牌(Royal Dutch Shell),投資替代能源都只是輕描淡寫。Wood Mackenzie估計前五大油商每年投資的1,000億美元中,只有3%用於再生能源。雪佛龍執行長John Watson說,目前沒有石油需求觸頂的跡象,未來10~20年,石油需求將持續成長。   能源巨擘信心滿滿,是看準新興市場的石油需求將持續增加。艾克森美孚估計,2040年亞洲的運輸需求將使得燃料需求提高25%。BP也說,全球生產石油中,有1/5用於汽車,如果電動車真的奪取大量市佔,空運、鐵路、卡車運輸仍會拉高石油需求。油商也大力投資天然氣,算準就算電動車起飛,天然氣能用於發電,需求仍會成長。   (本文內容由授權使用。首圖來源:pixabay)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司“嚨底家”!

※推薦評價好的iphone維修中心

聚甘新

砸錢不手軟,戴姆勒才是特斯拉頭號強敵?

  德國車廠戴姆勒(Daimler)豪擲110億美元,計劃在2020年打造電動車隊,出手之大無人出其右,儼然已成為特斯拉最可畏競爭者。   戴姆勒毫不避諱挑戰特斯拉,該公司九月宣布投資位在美國阿拉巴馬的廠房10億美元,計畫在2020年推出電動SUV,許多媒體認為這是在對特斯拉叫陣。   特斯拉執行長Elon Musk當時並不以為意,甚至推文嘲笑戴姆勒投資規模太小,金額後面少一個零,但沒想到戴姆勒隔一天即透過推特官方帳號宣布,研發下一代電動車經費加碼至100億美元以上,並外加至少10億美元開發電池產品。(BusinessInsider)   除此之外,戴姆勒今年三月還與太陽能面板安裝業者Vivint合作,在加州開展家用電池事業,似乎在模仿特斯拉打造以太陽能為基礎的電動車生態圈。   展望未來,中國可能是戴姆勒與特斯拉的最重要決戰場,因為中國是全球最大汽車市場,且未來準備禁賣汽/柴油車。特斯拉赴上海設廠計畫目前還在籌備階段,而戴姆勒七月已與北京汽車集團合資7.5億美元在中國建立電動車生產據點。   (本文內容由授權使用。首圖來源:public domain CC0)  

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

聚甘新

【asp.net core 系列】10 實戰之ActionFilter

0.前言

在上一篇中,我們提到了如何創建一個UnitOfWork並通過ActionFilter設置啟用。這一篇我們將簡單介紹一下ActionFilter以及如何利用ActionFilter,順便補齊一下上一篇的工具類。

1. ActionFilter 介紹

ActionFilter全稱是ActionFilterAttribute,我們根據微軟的命名規範可以看出這是一個特性類,看一下它的聲明:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class ActionFilterAttribute : Attribute, IActionFilter, IFilterMetadata, IAsyncActionFilter, IAsyncResultFilter, IOrderedFilter, IResultFilter

這是一個允許標註在類和方法上的特性類,允許多個標記,標註之後子類會繼承父類的特性。然後,這個類是一個抽象類,所以我們可以通過繼承ActionFilterAttribute來編寫自己的ActionFilter。

1.1 ActionFilter的四個方法

對於一個ActionFilter而言,最重要的是它的四個方法:

public virtual void OnActionExecuted(ActionExecutedContext context);
public virtual void OnActionExecuting(ActionExecutingContext context);

public virtual void OnResultExecuted(ResultExecutedContext context);
public virtual void OnResultExecuting(ResultExecutingContext context);

上圖是這四個方法在一次請求中執行的順序。在一次請求真正執行之前,想要攔截這個請求,應該使用OnActionExecuting

為什麼單獨說這個呢?因為這個方法的出鏡率很高,大多數時候都會使用這個方法進行請求過濾。

1.2 在ActionFilter中我們能做什麼

我們來簡單介紹一下,四個方法中的四種上下文類型,看一看裏面有哪些我們可以利用的方法:

1.2.1 ActionExecutingContext

這是一個Action執行前的上下文,表示Action並未開始執行,但是已經獲取到了控制器實例:

public class ActionExecutingContext : FilterContext
{
    public virtual IDictionary<string, object> ActionArguments { get; }
    public virtual object Controller { get; }
    public virtual IActionResult Result { get; set; }
}

ActionExecutingContext繼承自FilterContext,我們暫且不關注它的父類,只看一下它自己的屬性。

  • ActionArguments 表示Action的參數列表,這裏面放着各種從用戶接到請求參數以及其他中間處理程序添加的參數
  • Controller 表示執行該請求的控制器,在之前我們提過,asp.net core 對於控制器的限制很小,所以控制器什麼類型都可能,故而這裏使用object作為控制器類型
  • Result 執行結果,正常情況下,在此處獲取這個屬性的值沒有意義。但是我們可以通過修改這個屬性的值,來讓我們攔截請求

1.2.2 ActionExecutedContext

ActionExecutedContext 表示Action執行完成后的上下文,這時候Action已經執行完成,我們可以通過這個獲取Action執行結果:

public class ActionExecutedContext : FilterContext
{
    public virtual bool Canceled { get; set; }
    public virtual object Controller { get; }
    public virtual Exception Exception { get; set; }
    public virtual ExceptionDispatchInfo ExceptionDispatchInfo { get; set; }
    public virtual bool ExceptionHandled { get; set; }
    public virtual IActionResult Result { get; set; }
}

同樣,繼承自FilterContext,暫且忽略。

  • Canceled 表示是否被設置短路
  • Controller 處理請求的控制器
  • Exception 執行過程中是否發生異常,如果有異常則 有值,否則為Null
  • ExceptionHandled 異常是否被處理
  • Result 此處對Result進行修改不會屏蔽執行的ActionResult,但是可以向用戶隱藏對應的實現

1.2.3 ResultExecutingContext

這是在Result渲染之前執行的上下文,這時候Action已經執行完畢,正準備渲染Result:

public class ResultExecutingContext : FilterContext
{
    public virtual bool Cancel { get; set; }
    public virtual object Controller { get; }
    public virtual IActionResult Result { get; set; }
}
  • Cancel 取消當前結果執行以及後續篩選器的執行
  • Controller 控制器
  • Result 處理結果

1.2.4 ResultExecutedContext

Result已經執行完成了,獲取執行結果上下文:

public class ResultExecutedContext : FilterContext
{
    public virtual bool Canceled { get; set; }
    public virtual object Controller { get; }
    public virtual Exception Exception { get; set; }
    public virtual ExceptionDispatchInfo ExceptionDispatchInfo { get; set; }
    public virtual bool ExceptionHandled { get; set; }
    public virtual IActionResult Result { get; }
}

這個類與 ActionExecutedContext類似,就不做介紹了。

1.2.5 FilterContext

在上面的四個上下文都繼承自 FilterContext,那麼我們來看一下FilterContext中有哪些屬性或者方法:

public abstract class FilterContext : ActionContext
{
    public virtual IList<IFilterMetadata> Filters { get; }
    public TMetadata FindEffectivePolicy<TMetadata>() where TMetadata : IFilterMetadata;
}

可以看到FilterContext繼承了另一個ActionContext的類。小夥伴們應該對這個類要有一定的概念,這個類是Action的上下文類。它完整存在於一個Action的生命周期,所以有時候可以通過ActionContext進行Action級的數據傳遞(不推薦)。

那麼,繼續讓我們回過頭來看看ActionContext里有什麼:

public class ActionContext
{
    public ActionDescriptor ActionDescriptor { get; set; }
    public HttpContext HttpContext { get; set; }
    public ModelStateDictionary ModelState { get; }
    public RouteData RouteData { get; set; }
}
  • ActionDescriptor 執行的Action描述信息,包括Action的显示名稱、一些參數等,具體用到的時候,再為大夥詳細說
  • HttpContext 可以通過這個屬性獲取此次請求的Request和Response對象
  • ModelState 模型校驗信息, 這部分在後續再為小夥伴們細說
  • RouteData 路由信息,asp.net core 在處理請求時解析出來的路由信息,包括在程序中修改的路由信息

2. 使用ActionFilter

在《【asp.net core 系列】9 實戰之 UnitOfWork以及自定義代碼生成》也就是上一篇中,介紹到了ActionFilter與普通特性類一致,可以通過標註控制器然後啟用該ActionFilter。

因為大多數情況下,一個ActionFilter並不會僅僅局限於一個控制器,而是應用於多個控制器。所以這時候,我們通常會設置一個基礎控制器,在這個控制器上進行標註,然後讓子類繼承這個控制器。通過這種方式來實現一次聲明多次使用。

當然,在asp.net core 中添加了另外的一種使用ActionFilter的方式,Setup.cs中

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
}

默認是這樣的,我們可以通過設置參數來添加一個全局應用的Filter,例如說我們上一篇中創建的 UnitOfWorkFilterAttribute:

services.AddControllersWithViews(options=>
{
    options.Filters.Add<UnitOfWorkFilterAttribute>();
});

通過這種方式可以啟用一個全局ActionFilter。如果需要使用asp.net core的默認依賴注入可以使用 AddService進行配置。(依賴注入的內容在後續會講解)。

3. 工具類生成

繼續上一篇遺留的內容:

public static void CreateEntityTypeConfig(Type type)
{
    var targetNamespace = type.Namespace.Replace("Data.Models", "");
    if (targetNamespace.StartsWith("."))
    {
        targetNamespace = targetNamespace.Remove(0);
    }
    var targetDir = Path.Combine(new[] { CurrentDirect, "Domain.Implements", "EntityConfigures" }.Concat(
        targetNamespace.Split('.')).ToArray());

    if (!Directory.Exists(targetDir))
    {
        Directory.CreateDirectory(targetDir);
    }
    var baseName = type.Name.Replace("Entity", "");
    if (!string.IsNullOrEmpty(targetNamespace))
    {
        targetNamespace = $".{targetNamespace}";
    }

    var file = $"using {type.Namespace};" +
        $"\r\nusing Microsoft.EntityFrameworkCore;" +
        $"\r\nusing Microsoft.EntityFrameworkCore.Metadata.Builders;" +
        $"\r\nnamespace Domain.Implements.EntityConfigures{targetNamespace}" +
        "\r\n{" +
        $"\r\n\tpublic class {baseName}Config : IEntityTypeConfiguration<{type.Name}>" +
        "\r\n\t{" +
        "\r\n\t\tpublic void Configure(EntityTypeBuilder<SysUser> builder)" +
        "\r\n\t\t{" +
        $"\r\n\t\t\tbuilder.ToTable(\"{baseName}\");" +
        $"\r\n\t\t\tbuilder.HasKey(p => p.Id);" +
        "\r\n\t\t}\r\n\t}\r\n}";
    File.WriteAllText(Path.Combine(targetDir, $"{baseName}Config.cs"), file);
}

工具類其實本質上就是一次文件寫入的方法,本身沒什麼難度。

不過,這裏還有有個小問題,每次調用都會覆蓋原有的文件,還有就是這裏面有很多可以優化的地方,小夥伴們可以自己試試去優化一下,讓代碼更好看一點。

4 總結

到目前為止,實戰系列也有了幾篇,很多小夥伴問我能提供一下源碼嗎?當然,能呀。不過不是現在,容我留個謎底。當主要框架功能完成之後,我就會給小夥伴們發代碼的。

其實也是因為現在還沒個完整的,開放給小夥伴們也沒啥意義。當然了,跟着一塊敲,也是能實現的哈。關鍵地方的代碼都有。

更多內容煩請關注我的博客《高先生小屋》

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司“嚨底家”!

※推薦評價好的iphone維修中心

聚甘新

基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(九)

系列文章

  1. 基於 abp vNext 和 .NET Core 開發博客項目 – 使用 abp cli 搭建項目
  2. 基於 abp vNext 和 .NET Core 開發博客項目 – 給項目瘦身,讓它跑起來
  3. 基於 abp vNext 和 .NET Core 開發博客項目 – 完善與美化,Swagger登場
  4. 基於 abp vNext 和 .NET Core 開發博客項目 – 數據訪問和代碼優先
  5. 基於 abp vNext 和 .NET Core 開發博客項目 – 自定義倉儲之增刪改查
  6. 基於 abp vNext 和 .NET Core 開發博客項目 – 統一規範API,包裝返回模型
  7. 基於 abp vNext 和 .NET Core 開發博客項目 – 再說Swagger,分組、描述、小綠鎖
  8. 基於 abp vNext 和 .NET Core 開發博客項目 – 接入GitHub,用JWT保護你的API
  9. 基於 abp vNext 和 .NET Core 開發博客項目 – 異常處理和日誌記錄
  10. 基於 abp vNext 和 .NET Core 開發博客項目 – 使用Redis緩存數據
  11. 基於 abp vNext 和 .NET Core 開發博客項目 – 集成Hangfire實現定時任務處理
  12. 基於 abp vNext 和 .NET Core 開發博客項目 – 用AutoMapper搞定對象映射
  13. 基於 abp vNext 和 .NET Core 開發博客項目 – 定時任務最佳實戰(一)
  14. 基於 abp vNext 和 .NET Core 開發博客項目 – 定時任務最佳實戰(二)
  15. 基於 abp vNext 和 .NET Core 開發博客項目 – 定時任務最佳實戰(三)
  16. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(一)
  17. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(二)
  18. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(三)
  19. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(四)
  20. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(五)
  21. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(一)
  22. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(二)
  23. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(三)
  24. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(四)
  25. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(五)
  26. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(六)
  27. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(七)
  28. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(八)
  29. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(九)
  30. 基於 abp vNext 和 .NET Core 開發博客項目 – 終結篇之發布項目

終於要接近尾聲了,上一篇基本上將文章模塊的所有功能都完成了,整個博客頁面也都完成了,本篇主要來美化幾個地方,修修補補。

編輯器主題切換

當我們新增和編輯文章的時候,默認編輯器是白色的,如果點擊了頭部切換主題按鈕,我想要把編輯器主題顏色也做相應的改變該如何去實現呢?

剛好,editor.md是支持主題切換的,這就比較舒服了,直接按照要求調用對應的方法即可。

app.jsrenderEditor函數中我們已經自定義了三個參數themeeditorThemepreviewTheme,這三個參數就是來改變編輯器主題顏色的。

還是將值存在localStorage中,和我們博客的主題切換一樣,這裏叫editorTheme

theme: localStorage.editorTheme || 'default',
editorTheme: localStorage.editorTheme === 'dark' ? 'pastel-on-dark' : 'default',
previewTheme: localStorage.editorTheme || 'default',

默認從localStorage中取數據,如果沒取到的話,給對應的默認值。第二個參數有點特殊,用了一個三元表達式給不同的值。

然後在主題切換的時候也對編輯器做相應的調整即可。

打開Header.razor頭部組件,找到SwitchTheme()切換主題的方法,添加一句await Common.SwitchEditorTheme(currentTheme);

/// <summary>
/// 切換主題
/// </summary>
private async Task SwitchTheme()
{
    currentTheme = currentTheme == "Light" ? "Dark" : "Light";

    await Common.SetStorageAsync("theme", currentTheme);

    await Common.InvokeAsync("window.func.switchTheme");

    var uri = await Common.CurrentUri();
    if (uri.AbsolutePath.StartsWith("/admin/post"))
    {
        await Common.SwitchEditorTheme(currentTheme);
    }
}

將具體切換邏輯放到SwitchEditorTheme中,他接收一個參數currentTheme,用來判斷是切換黑的還是白的。

/// <summary>
/// 切換編輯器主題
/// </summary>
/// <param name="currentTheme"></param>
/// <returns></returns>
public async Task SwitchEditorTheme(string currentTheme)
{
    var editorTheme = currentTheme == "Light" ? "default" : "dark";

    await SetStorageAsync("editorTheme", editorTheme);

    await InvokeAsync("window.func.switchEditorTheme");
}

切換主題之前拿到當前URI對象,判斷當前請求的鏈接是否是新增和更新文章的那個頁面,即”/admin/post”,才去執行切換編輯器主題的方法,當不是這個頁面的時候,編輯器是沒有渲染出來的,如果也執行這段代碼就會報錯。

去看看效果。

文章詳情頁美化

現在的文章詳情頁是沒有將markdown格式渲染出來的,這裏還是使用editor.md提供的方法,因為需要加載幾個js文件,然後才能渲染樣式。

所以還是在app.js添加一段代碼。

renderMarkdown: async function () {
    await this._loadScript('./editor.md/lib/zepto.min.js').then(function () {
        func._loadScript('./editor.md/lib/marked.min.js').then(function () {
            func._loadScript('./editor.md/lib/prettify.min.js').then(function () {
                func._loadScript('./editor.md/editormd.js').then(function () {
                    editormd.markdownToHTML("content");
                });
            });
        });
    });
},

然後在文章詳情頁的組件Post.razor中修改代碼,當數據加載完成后調用renderMarkdown即可,然後還需要引用一個css文件editormd.preview.css

提供一下Post.razor最終的代碼。

@page "/post/{year:int}/{month:int}/{day:int}/{name}"

<link href="./editor.md/css/editormd.preview.css" rel="stylesheet" />

@if (post == null)
{
    <Loading />
}
else
{
    @if (post.Success)
    {
        var _post = post.Result;

        <article class="post-wrap">
            <header class="post-header">
                <h1 class="post-title">@_post.Title</h1>
                <div class="post-meta">
                    Author: <a itemprop="author" rel="author" href="javascript:;">@_post.Author</a>
                    <span class="post-time">
                        Date: <a href="javascript:;">@_post.CreationTime</a>
                    </span>
                    <span class="post-category">
                        Category:<a href="/category/@_post.Category.DisplayName/">@_post.Category.CategoryName</a>
                    </span>
                </div>
            </header>
            <div class="post-content" id="content">
                @((MarkupString)_post.Html)
            </div>
            <section class="post-copyright">
                <p class="copyright-item">
                    <span>Author:</span>
                    <span>@_post.Author</span>
                </p>
                <p class="copyright-item">
                    <span>Permalink:</span>
                    <span><a href="/post@_post.Url">https://meowv.com/post@_post.Url</a></span>
                </p>
                <p class="copyright-item">
                    <span>License:</span>
                    <span>本文採用<a target="_blank" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"> 知識共享 署名-非商業性使用-禁止演繹(CC BY-NC-ND)國際許可協議 </a>進行許可</span>
                </p>
            </section>
            <section class="post-tags">
                <div>
                    <span>Tag(s):</span>
                    <span class="tag">
                        @if (_post.Tags.Any())
                        {
                            @foreach (var tag in _post.Tags)
                            {
                                <a href="/tag/@tag.DisplayName/"># @tag.TagName</a>
                            }
                        }
                    </span>
                </div>
                <div>
                    <a @onclick="@(async () => await Common.NavigateTo("/posts"))">back</a>
                    <span>· </span>
                    <a href="/">home</a>
                </div>
            </section>
            <section class="post-nav">
                @if (_post.Previous != null)
                {
                    <a class="prev"
                       rel="prev"
                       @onclick="@(async () => await FetchData(_post.Previous.Url))"
                       href="/post@_post.Previous.Url">@_post.Previous.Title</a>
                }
                @if (_post.Next != null)
                {
                    <a class="next"
                       rel="next"
                       @onclick="@(async () => await FetchData(_post.Next.Url))"
                       href="/post@_post.Next.Url">
                        @_post.Next.Title
                    </a>
                }
            </section>
        </article>
    }
    else
    {
        <ErrorTip />
    }
}

@code {
    [Parameter]
    public int year { get; set; }

    [Parameter]
    public int month { get; set; }

    [Parameter]
    public int day { get; set; }

    [Parameter]
    public string name { get; set; }

    /// <summary>
    /// URL
    /// </summary>
    private string url => $"/{year}/{(month >= 10 ? month.ToString() : $"0{month}")}/{(day >= 10 ? day.ToString() : $"0{day}")}/{name}/";

    /// <summary>
    /// 文章詳情數據
    /// </summary>
    private ServiceResult<PostDetailDto> post;

    /// <summary>
    /// 初始化
    /// </summary>
    protected override async Task OnInitializedAsync()
    {
        await FetchData(url);
    }

    /// <summary>
    /// 請求數據,渲染頁面
    /// </summary>
    /// <param name="url"></param>
    /// <returns></returns>
    private async Task FetchData(string url, bool isPostNav = false)
    {
        post = await Http.GetFromJsonAsync<ServiceResult<PostDetailDto>>($"/blog/post?url={url}");
        await Common.InvokeAsync("window.func.renderMarkdown");
    }
}

到這裏整個開發工作便結束了,這裏只是一個小小的實戰系列記錄,沒有深層次的剖析研究Blazor的所有使用方式。

如果本系列對你有些許幫助,便是我最大的收穫,歡迎大家關注我的公眾號:阿星Plus。

開源地址:https://github.com/Meowv/Blog

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

聚甘新