2017-05-31 52 views
0

我正在調用一個Web API的MVC Web應用程序。在我的創建(POST)方法中,用戶將輸入數據庫中某些用戶的電子郵件地址。只有在電子郵件尚未存在於數據庫中的情況下,我纔有一張支票才能輸入電子郵件。如果它已經存在,我希望能夠向用戶顯示錯誤消息「電子郵件已存在」。如何在MVC調用Web API中向用戶顯示錯誤消息?

我以爲HttpStatusCode.NotFound, "Email exists already."會工作,但我認爲它只會在PostMan中顯示。我如何在MVC端顯示像ViewBag.ErrorMessage

API

public IHttpActionResult PostApprovedUsers(ApprovedUsers approvedUsers) 
{ 
    if (!ModelState.IsValid) 
    { 
     return BadRequest(ModelState); 
    } 

if (!db.ApprovedUsers.Any(u => u.Email == approvedUsers.Email)) 
{ 
    db.ApprovedUsers.Add(approvedUsers); 
    db.SaveChanges(); 
} 
else 
{ 
    return Content(HttpStatusCode.NotFound, "Email exists already."); 
} 
return CreatedAtRoute("DefaultApi", new { id = approvedUsers.Email }, approvedUsers); 

MVC創建

public ActionResult Create([Bind(Include = "Email,FirstName,LastName")] ApprovedUsers approvedUsers) 
{ 
    using (WebClient client = new WebClient()) 
    { 
     token = Session.GetDataFromSession<string>("access_token"); 
      client.Headers.Add("authorization", "Bearer " + token); 
      client.UploadValues(apiUrl, "POST", new NameValueCollection() 
      {      
       { "Email", approvedUsers.Email }, 
       { "FirstName",approvedUsers.FirstName }, 
       { "LastName",approvedUsers.LastName } 
      });     
    } 
    return RedirectToAction("Index"); 
} 
+1

您還沒有處理API的響應中創建的操作方法。在返回視圖之前,您需要檢查響應中的狀態碼並在viewbag中設置。 –

+0

@Luke - 他使用Webclient在他的創建控制器中進行調用。 OP:你有沒有這樣分離你的邏輯的理由?如果您正在編寫api和控制器,則沒有理由讓一個控制器調用另一個控制器。你應該在這裏使用一個通用的服務,並從創建控制器調用它。 – 2017-05-31 13:10:38

+0

@AndrewHunter我接手了其他人在我的實習中創建的這個項目。不知何故,我應該在下週完成它,這是一個混亂。特別是我是ASP.Net的新手。 – StraightUp

回答

1

你所看到的主要問題是你是事實上並沒有做任何與webclient的返回值有關的事情。不過,因爲基於我們的討論,所有內容都在同一個項目中,並且不會如何使用ASP.NET MVC和Web API執行此操作。

由於這些都在同一個項目中,所以我們希望將常用功能組合在一起,但不在控制器內。數據庫服務應該被抽象爲一個獨立的項目 - 或者類 - 然後使用某種形式的IoC Container注入到兩個控制器中。有幾個選項可用,我個人通常使用Ninject爲我的.NET項目。

假設您具有該功能,則您的MVC控制器和API控制器應該針對該抽象進行編程。 Interface based programming是.NET的最佳工作方式。

考慮到這一點新的API控制器將是這個樣子:

public IHttpActionResult PostApprovedUsers([Bind(Include="Email, FirstName, LastName")]ApprovedUser approvedUser) 
    { 
     if (!ModelState.IsValid) 
     { 
      return BadRequest(ModelState); 
     } 
     if (_db.UserExists(approvedUser)) 
     { 
      return Content(HttpStatusCode.NotFound, "Email exists Already"); 
     } 

     _db.AddUser(approvedUser); 
     return CreatedAtRoute("DefaultApi", new {id = approvedUser.Email}, approvedUser); 
    } 

哪裏_db是被注入到控制器的服務。請不怎麼常見的功能,比如檢查,看看用戶是否存在,並添加用戶都包裹抽象背後:

public interface IMyFakeDbService 
{ 
    IQueryable<ApprovedUser> ApprovedUsers { get; } 

    int RemoveUser(ApprovedUser user); 

    int RemoveUser(string email); 

    bool UserExists(ApprovedUser user); 

    void AddUser(ApprovedUser user); 
} 

這就給我們帶來了你的MVC控制器。同樣的原則適用;因爲所有通用功能都在db服務中,只需將其注入到控制器中,而不是調用API控制器。您會看到,您可以在此處使用ModelState.AddModelError將信息傳遞迴視圖。

public ActionResult Create() 
    { 
     return View(); 
    } 

    [HttpPost] 
    public ActionResult Create([Bind(Include = "Email, FirstName, LastName")]ApprovedUser user) 
    { 
     if (ModelState.IsValid) 
     { 
      if (!_db.UserExists(user)) 
      { 
       _db.AddUser(user); 
       return RedirectToAction("Index"); 
      } 
      ModelState.AddModelError("","A user with that email already exists"); 
     } 
     return View(); 
    } 

最後

  1. 我做了一個公共的git回購有一個完整的項目here
  2. 數據庫調用應該是async。如果不是
  3. 你是在浪費服務器資源,如果你想了解MVC真正的快,我建議Pro ASP.NET MVC 5Pro ASP.NET Web API2
+0

非常感謝您的幫助。真的很感激它。只是想問我如何添加令牌代碼? – StraightUp

+0

因此,您正在添加令牌代碼,因爲API位於某種形式的授權唯一屬性後面。您將爲該控制器中的MVC控制器處理安全性。您發佈的示例代碼沒有限制該控制器,它應該是? – 2017-06-01 13:43:37

+0

看起來您已經在控制器中設置了會話安全Cookie,因爲您可以從會話狀態'Session.GetDataFromSession (「access_token」);'訪問它。這意味着MVC控制器應該已經被保護,您可以直接調用該服務。 – 2017-06-01 13:47:01

0

我總是用Ok<T>,其中T是我定義了一個模型,它有3個變量,一個將識別的狀態(真,假),一個將是一個字符串消息,一個將有我需要在終點接收的數據類型List<object>,然後您可以修改錯誤消息a就是你在你的情況要 ,而不是這個

return BadRequest(ModelState);

我會的東西取代它這樣

return Ok<MyResponse>(new MyResponse{ Message = "Error Message Here", Status = false});

那麼一旦你得到你的內容,你可以desirialize到你的對象

MyResponse response = new MyResponse(); 
HttpResponseMessage response = await client.GetAsync(path); 
// ok will return success status code, but you will depend on your status to know if it was success or error happened 
if (response.IsSuccessStatusCode) 
{ 
    // Desirialize your result 
    response = await response.Content.ReadAsAsync<MyResponse>(); 
} 
// then get the message, 
if(response.Status) 
{ 
//it was fine, return something .. 
} 
else { 
// Error happened, get your error message and disaply it, if you want as viewbag 
ViewBag.ErrorMessage = response.Message; 
// do something 
} 
+0

@Muzner你有沒有一個我可以參考的例子以供參考?我試圖理解你的示例代碼,但我無法完全理解。你會在哪裏打電話回去Ok (新的MyResponse {消息=「錯誤消息在這裏」,狀態= false});'?我是否返回這個,而不是'返回RedirectToAction(「Index」);'? – StraightUp

+0

這是你的api返回,不是你的mvc控制器,api在出現錯誤時返回此信息,找不到示例電子郵件或模型無效,因此,而不是BadRequest返回我使用的那個,這樣就可以將錯誤消息修改爲你要。 – Munzer

相關問題