關於我

我的相片
用心思考、保持熱情,把工作上的經驗作分享與紀錄。希望能夠跟大家一起不斷的成長~
顯示具有 ASP.NET MVC 標籤的文章。 顯示所有文章
顯示具有 ASP.NET MVC 標籤的文章。 顯示所有文章

如何將MVC 2.0專案掛載於SharePoint(WSS)網站虛擬目錄下

如果在WSS環境下,希望可以在WSS網站虛擬目錄下直接掛載MVC專案。當使用VS2010 MVC2.0開啟MVC專案,並指定Web使用指向WSS下的虛擬目錄作為Web環境,這時會發現執行此MVC專案,會發生找不到路徑的錯誤。如下圖:
擷取1 

這是因為在.Net4.0中,已將UrlRoutingModule加入,Framework預設的Config中,如下圖:
擷取2 

所以在VS2010中,新建立的MVC 2.0 專案Web.config中,預設是不會有UrlRoutingModule的定義的,因為一般繼承Framework中的config設定,應該就可以正確運作了。

但SharePoint環境中,在HttpModule的宣告時,有特別把Framework的預設config部分Clear。因此掛在SharePoint網站下虛擬目錄之MVC專案,便無法正確被解讀了。如下圖參考:
擷取
知道原因後,這裡有兩個方式可以解決此問題:

  1. 把SharePoint的Web.cofig中,HttpModule區塊中的<Clear />拿掉。
  2. 在新的MVC專案中重新宣告UrlRoutingModule的定義。

我這裡選用第二種方式來解決我的問題。畢竟不瞭解為什麼SharePoint要清除上層的HttpModule設定,因此我想還是保留SharePoint預設值較佳,因此我在MVC專案的Web.config中加入如下區段:
擷取3
目前看起來MVC便可以正確運作了!

擷取5 
將這次問題經驗註記下來,分享給大家!

ASP.NET 4.0 加強 Request Validation

再使用ASP.NET MVC 時,有需求做線上Html編輯的功能。

結果在存檔時,一直發生下方錯誤訊息,將解決過程記錄下來!

擷取 

1.一般在ASP.NET 2.0 很直覺得先將該網頁的ValidateRequest="false"屬性加上。

擷取2

加上後,信心滿滿的認為已經解決了..結果一跑測試錯誤依舊發生..

2.便再進一步心想乾脆直接在Web.Config設定看看

擷取3

執行後錯誤還是一樣發生。

3.這時已經想不出其他原因了,便上網Google一下,很多文章都提到使用ASP.Net MVC時遇到此情況,可在Action處加上ValidateRequest="false"的屬性。變測試了一下這方法。

擷取4

測試後依舊不行 Orz

4.最後終於還是在Google上找到一篇重點了!!

可參考此篇文章,http://stackoverflow.com/questions/2019843/a-potentially-dangerous-request-form-value-in-mvc-2-asp-net-4-0

裡面提到 This is a documented breaking change in ASP.NET 4. See this whitepaper 

我將其中於ASP.NET 4.0 對於Request Validation 更新的說明部分截錄出來,如下:

ASP.NET Request Validation

The request validation feature in ASP.NET provides a certain level of default protection against cross-site scripting (XSS) attacks. In previous versions of ASP.NET, request validation was enabled by default. However, it applied only to ASP.NET pages (.aspx files and their class files) and only when those pages were executing.

In ASP.NET 4, by default, request validation is enabled for all requests, because it is enabled before the BeginRequest phase of an HTTP request. As a result, request validation applies to requests for all ASP.NET resources, not just .aspx page requests. This includes requests such as Web service calls and custom HTTP handlers. Request validation is also active when custom HTTP modules are reading the contents of an HTTP request.

As a result, request validation errors might now occur for requests that previously did not trigger errors. To revert to the behavior of the ASP.NET 2.0 request validation feature, add the following setting in the Web.config file:

<httpRuntime requestValidationMode="2.0" />

However, we recommend that you analyze any request validation errors to determine whether existing handlers, modules, or other custom code accesses potentially unsafe HTTP inputs that could be XSS attack vectors.

看到這裡,今天遇到的此問題的答案應該已經明瞭了!

原來是ASP.NET 4.0在Request驗證上,變得更嚴謹了!

以往Validation Request只對Asp.net 頁面的.aspx和codebeside .cs作用,一定要該網頁被執行,驗證才會做防護。

但於ASP.Net 4.0 將驗證防護,加強至Http BeginRequest時,便開始對Request做驗證!

因此包括WebService 甚至是自定義的HttpHandles、HttpModules都可做到驗證功能!

但這樣的驗證,很有可能讓一些既有程式發生驗證錯誤,

例如今天的Html編輯器需求,就一定會觸發到此驗證錯誤。

所以在ASP.NET 4.0可在Web.config中,設定要求執行時,驗證模式要使用2.0時的模式。

<httpRuntime requestValidationMode="2.0" />

擷取5

當然原文是不建議啦!!畢竟這樣就增加網站被攻擊的風險了!

 

另外想到,這樣的變更,如以後專案有需求要升級到ASP.NET 4.0。

也必須特別注意此問題!

ASP.NET MVC In-Depth: The Life of an ASP.NET MVC Request

今天在 Study MVC , 想了解整個的Life Cycle , 找到一篇不錯的文章 , 轉貼過來保存~

轉貼自 <http://stephenwalther.com/blog/archive/2008/03/18/asp-net-mvc-in-depth-the-life-of-an-asp-net-mvc-request.aspx>

The purpose of this blog entry is to describe, in painful detail, each step in the life of an ASP.NET MVC request from birth to death. I want to understand everything that happens when you type a URL in a browser and hit the enter key when requesting a page from an ASP.NET MVC website.

Why do I care? There are two reasons. First, one of the promises of ASP.NET MVC is that it will be a very extensible framework. For example, you’ll be able to plug in different view engines to control how your website content is rendered. You also will be able to manipulate how controllers get generated and assigned to particular requests. I want to walk through the steps involved in an ASP.NET MVC page request because I want to discover any and all of these extensibility points.

Second, I’m interested in Test-Driven Development. In order to write unit tests for controllers, I need to understand all of the controller dependencies. When writing my tests, I need to mock certain objects using a mocking framework such as Typemock Isolator or Rhino Mocks. If I don’t understand the page request lifecycle, I won’t be able to effectively mock it.

Two Warnings

But first, two warnings.

Here's the first warning: I’m writing this blog entry a week after the ASP.NET MVC Preview 2 was publicly released. The ASP.NET MVC framework is still very much in Beta. Therefore, anything that I describe in this blog entry might be outdated and, therefore, wrong in a couple of months. So, if you are reading this blog entry after May 2008, don’t believe everything you read.

Second, this blog entry is not meant as an overview of ASP.NET MVC. I describe the lifecycle of an ASP.NET MVC request in excruciating and difficult to read detail. Okay, you have been warned.

Overview of the Lifecycle Steps

There are five main steps that happen when you make a request from an ASP.NET MVC website:

1. Step 1 – The RouteTable is Created

This first step happens only once when an ASP.NET application first starts. The RouteTable maps URLs to handlers.

2. Step 2 – The UrlRoutingModule Intercepts the Request

This second step happens whenever you make a request. The UrlRoutingModule intercepts every request and creates and executes the right handler.

3. Step 3 – The MvcHandler Executes

The MvcHandler creates a controller, passes the controller a ControllerContext, and executes the controller.

4. Step 4 – The Controller Executes

The controller determines which controller method to execute, builds a list of parameters, and executes the method.

5. Step 5 – The RenderView Method is Called

Typically, a controller method calls RenderView() to render content back to the browser. The Controller.RenderView() method delegates its work to a particular ViewEngine.

Let’s examine each of these steps in detail.

Step 1 : The RouteTable is Created

When you request a page from a normal ASP.NET application, there is a page on disk that corresponds to each page request. For example, if you request a page named SomePage.aspx then there better be a page named SomePage.aspx sitting on your web server. If not, you receive an error.

Technically, an ASP.NET page represents a class. And, not just any class. An ASP.NET page is a handler. In other words, an ASP.NET page implements the IHttpHandler interface and has a ProcessRequest() method that gets called when you request the page. The ProcessRequest() method is responsible for generating the content that gets sent back to the browser.

So, the way that a normal ASP.NET application works is simple and intuitive. You request a page, the page request corresponds to a page on disk, the page executes its ProcessRequest() method and content gets sent back to the browser.

An ASP.NET MVC application does not work like this. When you request a page from an ASP.NET MVC application, there is no page on disk that corresponds to the request. Instead, the request is routed to a special class called a controller. The controller is responsible for generating the content that gets sent back to the browser.

When you write a normal ASP.NET application, you build a bunch of pages. There is always a one-to-one mapping between URLs and pages. Corresponding to each page request, there better be a page.

When you build an ASP.NET MVC application, in contrast, you build a bunch of controllers. The advantage of using controllers is that you can have a many-to-one mapping between URLs and pages. For example, all of the following URLs can be mapped to the same controller:

http://MySite/Products/1

http://MySite/Products/2

http://MySite/Products/3

The single controller mapped to these URLs can display product information for the right product by extracting the product Id from the URL. The controller approach is more flexible than the classic ASP.NET approach. The controller approach also results in more readable and intuitive URLs.

So, how does a particular page request get routed to a particular controller? An ASP.NET MVC application has something called a Route Table. The Route Table maps particular URLs to particular controllers.

An application has one and only one Route Table. This Route Table is setup in the Global.asax file. Listing 1 contains the default Global.asax file that you get when you create a new ASP.NET MVC Web Application project by using Visual Studio.

Listing 1 – Global.asax

1: using System;

2: using System.Collections.Generic;

3: using System.Linq;

4: using System.Web;

5: using System.Web.Mvc;

6: using System.Web.Routing;

7:

8: namespace TestMVCArch

9: {

10: public class GlobalApplication : System.Web.HttpApplication

11: {

12: public static void RegisterRoutes(RouteCollection routes)

13: {

14: // Note: Change the URL to "{controller}.mvc/{action}/{id}" to enable

15: // automatic support on IIS6 and IIS7 classic mode

16:

17: routes.Add(new Route("{controller}/{action}/{id}", new MvcRouteHandler())

18: {

19: Defaults = new RouteValueDictionary(new { action = "Index", id = "" }),

20: });

21:

22: routes.Add(new Route("Default.aspx", new MvcRouteHandler())

23: {

24: Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }),

25: });

26: }

27:

28: protected void Application_Start(object sender, EventArgs e)

29: {

30: RegisterRoutes(RouteTable.Routes);

31: }

32: }

33: }

An application’s Route Table is represented by the static RouteTable.Routes property. This property represents a collection of Route objects. In the Global.asax file in Listing 1, two Route objects are added to the Route Table when the application first starts (The Application_Start() method is called only once when the very first page is requested from a website).

A Route object is responsible for mapping URLs to handlers. In Listing 1, two Route objects are created. Both Route objects map URLs to the MvcRouteHandler. The first Route maps any URL that follows the pattern {controller}/{action}/{id} to the MvcRouteHandler. The second Route maps the particular URL Default.aspx to the MvcRouteHandler.

By the way, this new routing infrastructure can be used independently of an ASP.NET MVC application. The Global.asax file maps URLs to the MvcRouteHandler. However, you have the option of routing URLs to a different type of handler. The routing infrastructure described in this section is contained in a distinct assembly named System.Web.Routing.dll. You can use the routing without using the MVC.

Step 2 : The UrlRoutingModule Intercepts the Request

Whenever you make a request against an ASP.NET MVC application, the request is intercepted by the UrlRoutingModule HTTP Module. An HTTP Module is a special type of class that participates in each and every page request. For example, classic ASP.NET includes a FormsAuthenticationModule HTTP Module that is used to implement page access security using Forms Authentication.

When the UrlRoutingModule intercepts a request, the first thing the module does is to wrap up the current HttpContext in an HttpContextWrapper2 object. The HttpContextWrapper2 class, unlike the normal HttpContext class, derives from the HttpContextBase class. Creating a wrapper for HttpContext makes it easier to mock the class when you are using a Mock Object Framework such as Typemock Isolator or Rhino Mocks.

Next, the module passes the wrapped HttpContext to the RouteTable that was setup in the previous step. The HttpContext includes the URL, form parameters, query string parameters, and cookies associated with the current request. If a match can be made between the current request and one of the Route objects in the Route Table, then a RouteData object is returned.

If the UrlRoutingModule successfully retrieves a RouteData object then the module next creates a RouteContext object that represents the current HttpContext and RouteData. The module then instantiates a new HttpHandler based on the RouteTable and passes the RouteContext to the new handler’s constructor.

In the case of an ASP.NET MVC application, the handler returned from the RouteTable will always be an MvcHandler (The MvcRouteHandler returns an MvcHandler). Whenever the UrlRoutingModule can match the current request against a Route in the Route Table, an MvcHandler is instantiated with the current RouteContext.

The last step that the module performs is setting the MvcHandler as the current HTTP Handler. An ASP.NET application calls the ProcessRequest() method automatically on the current HTTP Handler which leads us to the next step.

Step 3 : The MvcHandler Executes

In the previous step, an MvcHandler that represents a particular RouteContext was set as the current HTTP Handler. An ASP.NET application always fires off a certain series of events including Start, BeginRequest, PostResolveRequestCache, PostMapRequestHandler, PreRequestHandlerExecute, and EndRequest events (there are a lot of application events – for a complete list, lookup the HttpApplication class in the Microsoft Visual Studio 2008 Documentation).

Everything described in the previous section happens during the PostResolveRequestCache and PostMapRequestHandler events. The ProcessRequest() method is called on the current HTTP Handler right after the PreRequestHandlerExecute event.

When ProcessRequest() is called on the MvcHandler object created in the previous section, a new controller is created. The controller is created from a ControllerFactory. This is an extensibility point since you can create your own ControllerFactory. The default ControllerFactory is named, appropriately enough, DefaultControllerFactory.

The RequestContext and the name of the controller are passed to the ControllerFactory.CreateController() method to get a particular controller. Next, a ControllerContext object is constructed from the RequestContext and the controller. Finally, the Execute() method is called on the controller class. The ControllerContext is passed to the Execute() method when the Execute() method is called.

Step 4 : The Controller Executes

The Execute() method starts by creating the TempData object (called the Flash object in the Ruby on Rails world). The TempData can be used to store temporary data that must be used with the very next request (TempData is like Session State with no long-term memory).

Next, the Execute() method builds a list of parameters from the request. These parameters, extracted from the request parameters, will act as method parameters. The parameters will be passed to whatever controller method gets executed.

The Execute() method finds a method of the controller to execute by using reflection on the controller class (.NET reflection and not navel gazing reflection). The controller class is something that you wrote. So the Execute() method finds one of the methods that you wrote for your controller class and executes it. The Execute() method will not execute any controller methods that are decorated with the NonAction attribute.

At this point in the lifecycle, we’ve entered your application code.

Step 5 : The RenderView Method is Called

Normally, your controller methods end with a call to either the RenderView() or RedirectToAction() method. The RenderView() method is responsible for rendering a view (a page) to the browser.

When you call a controller’s RenderView() method, the call is delegated to the current ViewEngine’s RenderView() method. The ViewEngine is another extensibility point. The default ViewEngine is the WebFormViewEngine. However, you can use another ViewEngine such as the NHaml ViewEngine.

The WebFormViewEngine.RenderView() method uses a class named the ViewLocator class to find the view. Next, it uses a BuildManager to create an instance of a ViewPage class from its path. Next, if the page has a master page, the location of the master page is set (again, using the ViewLocator class). If the page has ViewData, the ViewData is set. Finally, the RenderView() method is called on the ViewPage.

The ViewPage class derives from the base System.Web.UI.Page class. This is the same class that is used for pages in classic ASP.NET. The final action that RenderView() method performs is to call ProcessRequest() on the page class. Calling ProcessRequest() generates content from the view in the same way that content is generated from a normal ASP.NET page.

Extensibility Points

The ASP.NET MVC lifecycle was designed to include a number of extensibility points. These are points where you can customize the behavior of the framework by plugging in a custom class or overriding an existing class. Here’s a summary of these extensibility points:

1. Route objects – When you build the Route Table, you call the RouteCollection.Add() method to add new Route objects. The Add() method accepts a RouteBase object. You can implement your own Route objects that inherit from the base RouteBase class.

2. MvcRouteHandler – When building an MVC application, you map URLs to MvcRouteHandler objects. However, you can map a URL to any class that implements the IRouteHandler interface. The constructor for the Route class accepts any object that implements the IRouteHandler interface.

3. MvcRouteHandler.GetHttpHandler() – The GetHttpHandler() method of the MvcRouteHandler class is a virtual method. By default, an MvcRouteHandler returns an MvcHandler. If you prefer, you can return a different handler by overriding the GetHttpHandler() method.

4. ControllerFactory – You can assign a custom class by calling the System.Web.MVC.ControllerBuilder.Current.SetControllerFactory() method to create a custom controller factory. The controller factory is responsible for returning controllers for a given controller name and RequestContext.

5. Controller – You can implement a custom controller by implementing the IController interface. This interface has a single method: Execute(ControllerContext controllerContext).

6. ViewEngine – You can assign a custom ViewEngine to a controller. You assign a ViewEngine to a controller by assigning a ViewEngine to the public Controller.ViewEngine property. A ViewEngine must implement the IViewEngine interface which has a single method: RenderView(ViewContext viewContext).

7. ViewLocator – The ViewLocator maps view names to the actual view files. You can assign a custom ViewLocator to the default WebFormViewEngine.ViewLocator property.

If you can think of any other extensibility points that I overlooked, please add a comment to this blog post and I will update this entry.

Summary

The goal of this blog entry was to describe the entire life of an ASP.NET MVC request from birth to death. I examined the five steps involved in processing an ASP.NET MVC request: Creating the RouteTable, Intercepting the request with the UrlRoutingModule, Generating a Controller, Executing an Action, and Rendering a View. Finally, I talked about the points at which the ASP.NET MVC Framework can be extended.

Using FCK Editor with ASP.NET MVC

    此文章測試後,有一點必須注意的是,檔案上傳相關的功能,還需用到 FckEditor.Net 的功能..因此記得也要 Referance 進來喔!!

    FckEditor.Net下載連結,或 直接下載

    下載後解壓後,Referance 如下圖檔案:

    擷取

    擷取1

    上傳的功能才可以Work喔!!

     

    測試 FCK Editor 網頁 Html 編輯器,是否也可於ASP.NET MVC中使用,找到的好文章,轉貼如下:

    First of, what is this FCKEditor? Well, it's an HTML Text Editor. It's free and open source, cross browser, extensible and there are probably quite a few more buzzwords applicable. Oh... and it's also the default HTML Text Editor provided with DotNetNuke. Fck Editor is soon to be replaced by CK Editor but I'll stick with Fck for now. CK will work mostly the same though.

    clip_image001

    First, you'll need to download Fck Editor. Unzip the downloaded file to see what's in there.

    You'll need to copy the "editor" folder over to you Contents folder in you ASP.NET MVC website. I chose the path "/Content/Js/ Fck" to paste it in.

    Two other files you might want to copy over to this same folder are in the root of the downoaded zipfile: fckeditor.js and fckconfig.js. The latter is expected by the editor and (suprisingly) contains configuration settings for the editor, while the first contains a few nice javascript functions to instanciate the editor.

    clip_image002

    Next, include the fckeditor.js file in your page:

    <script src="<%= Url.Content("~/Content/Js/fck/fckeditor.js") %>" type="text/javascript" ></script> 

    All set. Now you'll need to add a textarea to your page:

    <%= Html.TextArea("FckEditor1", "Some Value", new { @name="FckEditor1" })%> 

    Important thing here, is the name property of the TextArea being set to the same value as the Id of it.

    To finish the client side of things off, you'l need to add some javascript to turn the textarea into a FckEditor at runtime. This can be copied from the samples of course, except for the Url.Contents part:

    <script type="text/javascript"> 
    window.onload = function() 
    { 
    var sBasePath = '<%= Url.Content("~/Content/Js/Fck/") %>'; 
    var oFCKeditor = new FCKeditor( 'FckEditor1' ) ; 
    oFCKeditor.BasePath = sBasePath ; 
    oFCKeditor.ReplaceTextarea() ; 
    } 
    </script> 

    Now, to prevent the server error "A potentially dangerous Request.Form value was detected from the client ", you should add the attribute "ValidateInput" to your controller's action method like this":

    [ValidateInput(false)] 
    public ActionResult Save(int id) 
    { 
    ... 
    }

    With this, you're all set. The contents of the TextArea field you started out with, will contain the contents of the FckEditor control.

    Have fun!

    本文參考自 <http://msmvps.com/blogs/superska/archive/2009/04/06/using-fck-editor-with-asp-net-mvc.aspx>