2014-01-22 2 views
5

WebApi 자체를 만들었으며 브라우저에서 찾아 출력을 얻을 수 있습니다.Asp.net MVC에서 WebApi를 추가 한 다음 동일한 응용 프로그램에서 WebAPI를 사용하는 방법

나를 위해 작동하지 않는 것은 MVC 컨트롤러에서 WebAPI를 소비하려고하는데 "cshtml"뷰에서 WebAPI를 호출하기위한 코드를 작성했습니다.

하지만 페이지가로드되는 동안 오류가 발생하여 작동하지 않습니다. 잘못된 것으로 알고 있습니다. 그래서 첫 번째 질문은 다음과 같습니다. 올바르게 수행하고 있습니까? 또는 MVC 프로젝트에서 WebAPI 부분을 만든 다음 컨트롤러에서 동일한 MVC 프로젝트에서이 부분을 사용하려고하면 완전히 잘못 되었습니까?

+0

오류 게시. 그러나 왜 응용 프로그램이 이미 서비스가 캡슐화하고있는 모든 코드에 액세스 할 수 있다고 가정 할 때 동일한 응용 프로그램에서 웹 API를 사용하려고합니까? 필요하지 않을 때 여분의 오버 헤드를 소비하는 이유는 무엇입니까? – Maess

+1

전적으로 당신의 의견에 동의하지만 기술적 인 이유가 있습니까? 아니면 그것을 구현할 수없는 잘못된 방법일까요? – user1570094

+1

@Maess, MVC 및 WebAPI는 동일한 응용 프로그램에 존재하도록 설계되었습니다. 원하는 경우 특정 API 컨트롤러를 별도의 폴더 (예 : "API")에 루트 디렉토리로 보내어 구분할 수 있습니다. 동일한 RouteConfig.cs와 WebApiConfig.cs가 동일한 App_Start 폴더에있는 이유입니다. 왜냐하면 같은 프로젝트에서 두 가지를 모두 활용할 것으로 예상되기 때문입니다. 그것은 필수는 아니지만. –

답변

2

질문에 대답하기 위해 실제로는 "설계대로"이며 WebAPI 및 MVC 클라이언트를 동일한 프로젝트 내에 두는 것이 좋습니다. 따라서 MVC 프로젝트 내에 RouteConfig.csWebApiConfig.cs이 모두있는 것입니다. RouteConfig.cs은 MVC 컨트롤러 용이고 WebApiConfig.cs은 Api 컨트롤러 용입니다.

두 프로젝트를 같은 프로젝트에 포함시키는 것이 쉽습니다. 내가하는 일은 루트에 "API"라는 폴더를 추가하고 거기에 모든 WebAPI 컨트롤러를 배치하는 것입니다. 웹API 컨트롤러와 MVC 컨트롤러의 유일한 차이점은 이 System.Web.Http (저는 믿습니다)의 일부분이라는 것입니다. MVC 컨트롤러가 일부인 Controller을 상속하는 반면에, 저는 믿습니다. System.Web.MVC.

다음은/GET/PUT을 POST가 MVC 프론트 엔드에서 WebAPI TO 를 요청/삭제하는 적절한 방법입니다. 컨트롤러의 생성자에서 WebAPI URL을 지정하기 때문에 동일한 프로젝트에 있는지 여부는 중요하지 않습니다. WebAPI가 프런트 엔드 MVC 응용 프로그램과 다른 서버에있는 경우 WebAPI 버전 2 이상에서 사용할 수있는 CORS 지원을 활성화해야합니다.

프런트 엔드 MVC 클라이언트에서 WebAPI를 호출하는 적절한 방법입니다.

컨트롤러 페이지에서 DbContext, Entity Framework 등과 관련이있는 것은 제거하십시오. 기본적으로 컨트롤러는 DbContext를 호출하여 CRUD 작업을 수행하기를 원하므로이 작업을 원하지 않습니다. 우리는 이것을 대신 WebAPI를 호출하기를 원합니다. "컨트롤러"를 참조 할 때 WebAPI 컨트롤러가 아니라 MVC 컨트롤러를 참조합니다.

맨 먼저 MVC 컨트롤러에서 일부 멤버 변수를 선언하십시오. 같은 컨트롤러의 생성자를 만들고, 당신의 MVC 컨트롤러에서

HttpClient client = new HttpClient(); 
    HttpResponseMessage response = new HttpResponseMessage(); 
    Uri contactUri = null; 
  1. 을 : 당신의 MVC 컨트롤러의 나머지 부분은 다음을 사용합니다

    public ContactController() 
    { 
        // set base address of WebAPI depending on your current environment 
        // the URL below, if the API is in the same project, will be something 
        // like "http://server/YourProjectName" - replace server with either 
        // "localhost", etc. 
        client.BaseAddress = new Uri("http://server/YourAPI/"); 
    
        // Add an Accept header for JSON format. 
        client.DefaultRequestHeaders.Accept.Add(
         new MediaTypeWithQualityHeaderValue("application/json")); 
    } 
    
  2. 뭔가 색인 작업의 코드를 바꿉니다 다음과 같이. 관련 부분은 client.GetAsync() 전화와 var contacts 지정 사항입니다. 이 문제의 맥락에서는 다른 모든 것이 필요하지 않습니다. client.GetAsync() 안의 값은 컨트롤러의 이름이어야하며 WebApiConfig에 설정 한 사용자 지정 라우팅이 앞에 추가되어야합니다.CS는 - 내 경우, 나는 API 호출과 정상 걸려 오는 전화를 구별 할 수 있도록 내 경로에 api 부분을 추가 :

    public ActionResult Index() 
    { 
        response = client.GetAsync("api/contact").Result; 
        if (response.IsSuccessStatusCode) 
        { 
         var contacts = response.Content.ReadAsAsync<IEnumerable<Contact>>().Result; 
         return View(contacts); 
        } 
        else 
        { 
         // add something here to tell the user hey, something went wrong 
         return RedirectToAction("Index"); 
        } 
    } 
    
  3. 는 다음과 같은으로 활동 작성합니다 (HttpPost 조치)를 교체합니다. 합니다 (

    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Create(Contact contact) 
    { 
        // Create a new product 
        response = client.PostAsJsonAsync("api/contact", contact).Result; 
        if (response.IsSuccessStatusCode) 
        { 
         return RedirectToAction("Index"); 
        } 
        else 
        { 
         // add something here to tell the user hey, something went wrong 
         return RedirectToAction("Index"); 
        } 
    } 
    
  4. 편집 작업을 바꾸기 :이 데이터베이스에 새 레코드를 삽입, 내 경우에는, 처리 걸리는 WebAPI의 POST 액션을 호출하는 것입니다 - 다시 말하지만, 유일한 중요한 부분은 client.PostAsJsonAsync() 부분은 비 HttpPost 조치)를 다음과 같이 사용하십시오. 이는 편집하기 위해 먼저 레코드를 검색해야했기 때문에 기본적으로 HttpPost 버전의 편집에는 POST (편집 POST)를 수행하는 추가 코드 줄이 포함 된 유사한 코드가 포함됩니다. 아래에서 우리는 특정 레코드 ID를 전달하여 WebAPI의 응답을 받고 있습니다. 따라서 Index (GET)와 마찬가지로 ID를 전달하는 것과 동일한 작업을 수행하므로 하나의 레코드 만 반환합니다.

    public ActionResult Edit(int id = 0) 
    { 
        response = client.GetAsync(string.Format("api/contact/{0}", id)).Result; 
        Contact contact = response.Content.ReadAsAsync<Contact>().Result; 
        if (contact == null) 
        { 
         return HttpNotFound(); 
        } 
        return View(contact); 
    } 
    
  5. 는 다음과 같은과 편집 작업을합니다 (HttpPost 동작을) 교체 : 그럼, 우리가보기에 수술을 할 수있는 실제 객체에 대한 응답을 캐스팅. 아래에서 우리는 client.GetAsync()을 호출하고 기본 키를 매개 변수 (contact_id)로 전달하여 편집 할 레코드를 얻게됩니다. 그런 다음 해당 응답에서 RequestUri를 가져 와서 저장합니다. 그런 다음 client.PutAsJsonAsync()을 호출하고 Uri.PathAndQuery (방금 저장 한 것)와 편집 할 개체를 전달합니다.

    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public ActionResult Edit(Contact contact) 
    { 
        response = client.GetAsync(string.Format("api/contact/{0}", contact.contact_id)).Result; 
        contactUri = response.RequestMessage.RequestUri; 
        response = client.PutAsJsonAsync(contactUri.PathAndQuery, contact).Result; 
        if (response.IsSuccessStatusCode) 
        { 
         return RedirectToAction("Index"); 
        } 
        else 
        { 
         // add something here to tell the user hey, something went wrong 
         return RedirectToAction("Index"); 
        } 
    } 
    
  6. 삭제 (비 HttpPost 작업) 동작을 다음과 같이 바꿉니다. 다시 한번 우리는 데이터베이스에서 레코드를 얻고 있습니다. client.GetAsync()을 호출하고 내 앱이 아는 실제 객체로 캐스팅합니다.

    public ActionResult Delete(int id = 0) 
    { 
        response = client.GetAsync(string.Format("api/contact/{0}", id)).Result; 
        Contact contact = response.Content.ReadAsAsync<Contact>().Result; 
    
        if (contact == null) 
        { 
         return HttpNotFound(); 
        } 
        return View(contact); 
    } 
    
  7. 마지막으로 삭제 동작 (HttpPost 동작)을 다음과 같이 바꿉니다. 다시, 우리는 편집 동작과 비슷한 것을하고 있습니다. 레코드를 삭제하고 객체로 캐스팅 한 다음 해당 객체를 아래 그림과 같이 client.DeleteAsync() 호출로 전달합니다.

    [HttpPost, ActionName("Delete")] 
    [ValidateAntiForgeryToken] 
    public ActionResult DeleteConfirmed(int id) 
    { 
        response = client.GetAsync(string.Format("api/contact/{0}", id)).Result; 
        contactUri = response.RequestMessage.RequestUri; 
        response = client.DeleteAsync(contactUri).Result; 
        return RedirectToAction("Index"); 
    } 
    
+0

이 상세하고 훌륭한 설명을 해주셔서 감사 드리며 완전히 간다. 그러나 동일한 프로젝트에서 WebApi 및 MVC 클라이언트가있는 이와 비슷한 시나리오에서 뷰에 jquery를 작성하여 WebApi에 액세스 할 수 있으며 해당 뷰가 MVC 컨트롤러에 의해 ActionResult로 반환됩니까? 제 생각에는 그것이 효과가 있다고 생각하기 때문에 이에 대한 답을 제게 제공 해주시기 바랍니다. 나는 이것을 시도했지만 효과가 없었다. 감사. – user1570094

+0

좋은 답변이지만 로그인 정보는 무엇입니까?WebAPI 컨트롤러를 통해 [Authorize] 특성을 사용하면 어떻게 코드가 변경됩니까? 제발, 분명히 해줘. 고맙습니다! –

+0

2 단계에서 'public ActionResult Index()'와 같은 액션 인덱스 코드를 추가하여 web-api-2를 사용하여 문제가 발생했습니다. 이 질문에 근거하여 (왜 ... -httpactionresult-대신 -httpresponsemessage 대신에) (http://stackoverflow.com/questions/21758615/) web-api-2의 경우 2 단계의 코드가 있어야한다고 가정합니다. 'public IHttpActionResult Index()'로 변경되었습니다. 이 올바른지? – surfmuggle

관련 문제