Asp.net MVC ModelState ล้าง


116

ใครช่วยให้คำจำกัดความสั้น ๆ เกี่ยวกับบทบาทของ ModelState ใน Asp.net MVC (หรือลิงก์ไปยังหนึ่ง) ModelState.Clear()โดยเฉพาะอย่างยิ่งผมจำเป็นต้องรู้ในสิ่งที่สถานการณ์มันเป็นสิ่งจำเป็นหรือพึงปรารถนาที่จะโทร

บิตเปิดจบแล้วฮะ ... ขอโทษนะฉันคิดว่ามันอาจช่วยได้ถ้าบอกคุณว่าฉันกำลังทำอะไรอยู่:

ฉันมีการดำเนินการแก้ไขในคอนโทรลเลอร์ชื่อ "เพจ" เมื่อฉันเห็นแบบฟอร์มเพื่อเปลี่ยนรายละเอียดของเพจเป็นครั้งแรกทุกอย่างโหลดได้ดี (เชื่อมโยงกับวัตถุ "MyCmsPage") จากนั้นฉันคลิกปุ่มที่สร้างค่าสำหรับฟิลด์ของวัตถุ MyCmsPage ( MyCmsPage.SeoTitle) มันสร้างดีและอัปเดตออบเจ็กต์จากนั้นฉันจะส่งคืนผลลัพธ์การดำเนินการด้วยออบเจ็กต์เพจที่แก้ไขใหม่และคาดว่ากล่องข้อความที่เกี่ยวข้อง (แสดงผลโดยใช้<%= Html.TextBox("seoTitle", page.SeoTitle)%>) จะได้รับการอัปเดต ... แต่อนิจจามันแสดงค่าจากโมเดลเก่าที่โหลด

ฉันได้แก้ไขมันโดยใช้ModelState.Clear()แต่ฉันต้องการรู้ว่าทำไม / มันทำงานอย่างไรดังนั้นฉันจึงไม่ได้ทำแบบสุ่มสี่สุ่มห้า

PageController:

[AcceptVerbs("POST")]
public ActionResult Edit(MyCmsPage page, string submitButton)
{
    // add the seoTitle to the current page object
    page.GenerateSeoTitle();

    // why must I do this?
    ModelState.Clear();

    // return the modified page object
     return View(page);
 }

aspx:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyCmsPage>" %>
....
        <div class="c">
            <label for="seoTitle">
                Seo Title</label>
            <%= Html.TextBox("seoTitle", page.SeoTitle)%>
            <input type="submit" value="Generate Seo Title" name="submitButton" />
        </div>

Noob AspMVC ถ้าต้องการแคชข้อมูลเก่าแล้วอะไรคือประเด็นในการให้โมเดลแก่ผู้ใช้อีกครั้ง: @ ฉันมีปัญหาเดียวกันขอบคุณมากครับ
deadManN

คำตอบ:


135

ฉันคิดว่าเป็นจุดบกพร่องใน MVC ฉันต่อสู้กับปัญหานี้มาหลายชั่วโมงแล้วในวันนี้

ให้สิ่งนี้:

public ViewResult SomeAction(SomeModel model) 
{
    model.SomeString = "some value";
    return View(model); 
}

มุมมองแสดงผลด้วยโมเดลดั้งเดิมโดยไม่สนใจการเปลี่ยนแปลง ฉันก็เลยคิดว่าบางทีมันอาจจะไม่ชอบที่ฉันใช้รุ่นเดียวกันฉันก็เลยลองทำแบบนี้:

public ViewResult SomeAction(SomeModel model) 
{
    var newModel = new SomeModel { SomeString = "some value" };
    return View(newModel); 
}

และยังคงมุมมองที่แสดงผลด้วยโมเดลเดิม สิ่งที่แปลกคือเมื่อฉันใส่เบรกพอยต์ในมุมมองและตรวจสอบโมเดลมันมีค่าที่เปลี่ยนไป แต่กระแสตอบรับมีค่านิยมเก่า

ในที่สุดฉันก็ค้นพบวิธีแก้ปัญหาเดียวกันกับที่คุณทำ:

public ViewResult SomeAction(SomeModel model) 
{
    var newModel = new SomeModel { SomeString = "some value" };
    ModelState.Clear();
    return View(newModel); 
}

ทำงานได้ตามที่คาดไว้

ฉันไม่คิดว่านี่คือ "คุณลักษณะ" ใช่หรือไม่


33
เพิ่งทำสิ่งเดียวกับคุณ พบว่านี่ไม่ใช่ข้อผิดพลาดแม้ว่า โดยการออกแบบ: ข้อผิดพลาด? EditorFor และ DisplayFor ไม่แสดงค่าเดียวกันและตัวช่วย Html ของ ASP.NET MVC
Metro Smurf

8
ผู้ชายฉันใช้เวลา 2 ชั่วโมงในการต่อสู้กับมันแล้ว ขอบคุณที่โพสต์คำตอบนี้!
Andrey Agibalov

37
นี่ยังคงเป็นเรื่องจริงและผู้คนจำนวนมากรวมทั้งฉันก็เสียเวลาไปมากเพราะเหตุนี้ จุดบกพร่องหรือโดยการออกแบบฉันไม่สนใจมัน "ไม่คาดคิด"
Proviste

7
ฉันเห็นด้วยกับ @Proviste ฉันหวังว่า "คุณลักษณะ" นี้จะถูกลบออกในอนาคต
Ben

8
ฉันใช้เวลาสี่ชั่วโมงกับสิ่งนี้ น่าเกลียด
Brian MacKay

46

ปรับปรุง:

  • นี่ไม่ใช่บั๊ก
  • โปรดหยุดกลับView()จากการดำเนินการ POST ใช้PRGแทนและเปลี่ยนเส้นทางไปยัง GET หากการดำเนินการสำเร็จ
  • หากคุณกำลังกลับView()จากการกระทำ POST, ทำเพื่อตรวจสอบรูปแบบและทำมันทางMVC ถูกออกแบบมาใช้ในการสร้างผู้ช่วยเหลือ หากคุณทำเช่นนี้คุณไม่จำเป็นต้องใช้.Clear()
  • หากคุณกำลังใช้การกระทำนี้เพื่อส่งคืน ajax สำหรับSPAให้ใช้ตัวควบคุม web api และอย่าลืมModelStateเพราะคุณไม่ควรใช้มันต่อไป

คำตอบเก่า:

ModelState ใน MVC ถูกใช้เพื่ออธิบายสถานะของโมเดลออบเจ็กต์เป็นหลักโดยมีความสัมพันธ์ว่าวัตถุนั้นถูกต้องหรือไม่ บทแนะนำนี้ควรอธิบายได้มาก

โดยทั่วไปคุณไม่จำเป็นต้องล้าง ModelState เนื่องจากได้รับการดูแลโดยเอ็นจิ้น MVC สำหรับคุณ การล้างด้วยตนเองอาจทำให้ได้ผลลัพธ์ที่ไม่ต้องการเมื่อพยายามปฏิบัติตามแนวทางปฏิบัติที่ดีที่สุดในการตรวจสอบความถูกต้องของ MVC

ดูเหมือนว่าคุณกำลังพยายามตั้งค่าเริ่มต้นสำหรับชื่อเรื่อง สิ่งนี้ควรทำเมื่อวัตถุโมเดลถูกสร้างอินสแตนซ์ (เลเยอร์โดเมนที่ใดที่หนึ่งหรือในอ็อบเจ็กต์เอง - ctor ที่ไม่มีพารามิเตอร์) ในการดำเนินการรับเช่นนั้นจะลงไปที่หน้าในครั้งที่ 1 หรือทั้งหมดบนไคลเอนต์ (ผ่าน ajax หรือบางอย่าง) เพื่อให้ดูเหมือนว่าผู้ใช้ป้อนและกลับมาพร้อมกับคอลเลกชันแบบฟอร์มที่โพสต์ วิธีการเพิ่มค่านี้ของคุณในการรับคอลเลกชันแบบฟอร์ม (ในการดำเนินการ POST // แก้ไข) ทำให้เกิดพฤติกรรมที่แปลกประหลาดนี้ซึ่งอาจส่งผลให้.Clear() ดูเหมือนว่าคุณจะได้ผล เชื่อฉัน - คุณไม่ต้องการใช้ความชัดเจน ลองใช้แนวคิดอื่น ๆ


1
ช่วยให้ฉันคิดใหม่ในชั้นบริการของฉันได้เล็กน้อย (คร่ำครวญ แต่ขอบคุณ) แต่เช่นเดียวกับสิ่งต่างๆมากมายบนอินเทอร์เน็ตมันโน้มน้าวอย่างมากต่อมุมมองของการใช้ ModelState เพื่อการตรวจสอบความถูกต้อง
Mr Grok

เพิ่มข้อมูลเพิ่มเติมในคำถามเพื่อแสดงว่าเหตุใดฉันจึงสนใจ ModelState.Clear () เป็นพิเศษและเหตุผลสำหรับคำถามของฉัน
Mr Grok

5
ฉันไม่ได้ซื้ออาร์กิวเมนต์นี้เพื่อหยุดส่งคืน View (... ) จากฟังก์ชัน [HttpPost] หากคุณกำลังโพสต์เนื้อหาผ่าน ajax แล้วอัปเดตเอกสารด้วย PartialView ผลลัพธ์ MVC ModelState ถูกแสดงว่าไม่ถูกต้อง วิธีแก้ปัญหาเดียวที่ฉันพบคือการล้างมันในวิธีการควบคุม
Aaron Hudon

@AaronHudon PRG เป็นที่ยอมรับ
Matt Kocaj

ถ้าฉันโพสต์ด้วยการเรียก AJAX ฉันสามารถเปลี่ยนเส้นทางไปยังการดำเนินการ GET และส่งคืนมุมมองที่เต็มไปด้วยโมเดลอย่างที่ OP ต้องการทั้งหมดแบบอะซิงโครนัสได้หรือไม่
MyiEye

17

หากคุณต้องการล้างค่าสำหรับแต่ละฟิลด์ฉันพบว่าเทคนิคต่อไปนี้มีประโยชน์

ModelState.SetModelValue("Key", new ValueProviderResult(null, string.Empty, CultureInfo.InvariantCulture));

หมายเหตุ: เปลี่ยน "คีย์" เป็นชื่อของฟิลด์ที่คุณต้องการรีเซ็ต


ฉันไม่รู้ว่าทำไมสิ่งนี้ถึงได้ผลสำหรับฉัน (MVC4 อาจ)? แต่ฉันก็ต้องทำ model.Key = "" หลังจากนั้นด้วย ต้องระบุทั้งสองบรรทัด
ท.ท.

ฉันขอชมเชยคุณในการลบความคิดเห็น @PeterGluck ดีกว่าการล้าง modelstate ทั้งหมด (เนื่องจากฉันมีข้อผิดพลาดในบางช่องที่ฉันต้องการเก็บไว้)
Tjab

6

โดยทั่วไปแล้ว ModelState จะถือสถานะปัจจุบันของโมเดลในแง่ของการตรวจสอบความถูกต้อง

ModelErrorCollection:แสดงข้อผิดพลาดเมื่อโมเดลพยายามผูกค่า อดีต

TryUpdateModel();
UpdateModel();

หรือชอบพารามิเตอร์ใน ActionResult

public ActionResult Create(Person person)

ValueProviderResult : เก็บรายละเอียดเกี่ยวกับการพยายามเชื่อมโยงกับโมเดล อดีต AttemptedValue วัฒนธรรม RawValue

ต้องใช้เมธอด Clear () ด้วยความระมัดระวังเนื่องจากอาจนำไปสู่ผลลัพธ์ที่ไม่สามารถตรวจสอบได้ และคุณจะสูญเสียคุณสมบัติที่ดีบางอย่างของ ModelState เช่น AttemptedValue ซึ่ง MVC จะใช้ในพื้นหลังเพื่อสร้างค่าฟอร์มใหม่ในกรณีที่เกิดข้อผิดพลาด

ModelState["a"].Value.AttemptedValue

1
อืม ... นั่นอาจเป็นจุดที่ฉันได้รับปัญหาจากรูปลักษณ์ของมัน ฉันได้ตรวจสอบค่าของคุณสมบัติ Model.SeoTitle แล้วและมีการเปลี่ยนแปลง แต่ค่าที่พยายามไม่ได้ ดูเหมือนว่าจะติดค่าเข้าด้วยกันราวกับว่ามีข้อผิดพลาดในหน้าแม้ว่าจะไม่มีก็ตาม (ตรวจสอบพจนานุกรม ModelState แล้วและไม่มีข้อผิดพลาด)
Mr Grok

6

ฉันมีอินสแตนซ์ที่ฉันต้องการอัปเดตโมเดลของแบบฟอร์ม sumitted และไม่ต้องการ 'เปลี่ยนเส้นทางไปที่การดำเนินการ' ด้วยเหตุผลทางการแสดง ค่าก่อนหน้าของฟิลด์ที่ซ่อนอยู่ถูกเก็บไว้ในโมเดลที่อัปเดตของฉันซึ่งทำให้เกิดปัญหาทุกประเภท!

โค้ดสองสามบรรทัดในไม่ช้าก็ระบุองค์ประกอบภายใน ModelState ที่ฉันต้องการลบ (หลังการตรวจสอบความถูกต้อง) ดังนั้นจึงใช้ค่าใหม่ในรูปแบบ: -

while (ModelState.FirstOrDefault(ms => ms.Key.ToString().StartsWith("SearchResult")).Value != null)
{
    ModelState.Remove(ModelState.FirstOrDefault(ms => ms.Key.ToString().StartsWith("SearchResult")));
}

5

ดูเหมือนว่าพวกเราหลายคนจะถูกกัดด้วยสิ่งนี้และแม้ว่าเหตุผลที่เกิดขึ้นจะสมเหตุสมผล แต่ฉันก็ต้องการวิธีที่จะทำให้แน่ใจว่าค่าใน Model ของฉันแสดงอยู่ไม่ใช่ ModelState

มีบางคนแนะนำModelState.Remove(string key)แต่ไม่ชัดเจนว่ามีอะไรบ้างkeyควรเป็นอย่างไรโดยเฉพาะอย่างยิ่งสำหรับรุ่นที่ซ้อนกัน นี่คือสองวิธีที่ฉันคิดขึ้นเพื่อช่วยในเรื่องนี้

RemoveStateForวิธีการจะใช้ModelStateDictionaryเป็นรุ่นและการแสดงออกสำหรับคุณสมบัติที่ต้องการและลบออก HiddenForModelสามารถใช้ใน View ของคุณเพื่อสร้างฟิลด์อินพุตที่ซ่อนอยู่โดยใช้เฉพาะค่าจาก Model โดยลบรายการ ModelState ออกก่อน (สิ่งนี้สามารถขยายได้อย่างง่ายดายสำหรับวิธีการขยายตัวช่วยอื่น ๆ )

/// <summary>
/// Returns a hidden input field for the specified property. The corresponding value will first be removed from
/// the ModelState to ensure that the current Model value is shown.
/// </summary>
public static MvcHtmlString HiddenForModel<TModel, TProperty>(this HtmlHelper<TModel> helper,
    Expression<Func<TModel, TProperty>> expression)
{
    RemoveStateFor(helper.ViewData.ModelState, helper.ViewData.Model, expression);
    return helper.HiddenFor(expression);
}

/// <summary>
/// Removes the ModelState entry corresponding to the specified property on the model. Call this when changing
/// Model values on the server after a postback, to prevent ModelState entries from taking precedence.
/// </summary>
public static void RemoveStateFor<TModel, TProperty>(this ModelStateDictionary modelState, TModel model,
    Expression<Func<TModel, TProperty>> expression)
{
    var key = ExpressionHelper.GetExpressionText(expression);

    modelState.Remove(key);
}

โทรจากคอนโทรลเลอร์เช่นนี้:

ModelState.RemoveStateFor(model, m => m.MySubProperty.MySubValue);

หรือจากมุมมองเช่นนี้:

@Html.HiddenForModel(m => m.MySubProperty.MySubValue)

ใช้System.Web.Mvc.ExpressionHelperเพื่อรับชื่อของคุณสมบัติ ModelState


1
ดีมาก! ติดตามแท็บนี้สำหรับฟังก์ชัน ExpressionHelper
Gerard ONeill

4

ฉันต้องการอัปเดตหรือรีเซ็ตค่าหากไม่สามารถตรวจสอบความถูกต้องได้และพบปัญหานี้

คำตอบง่ายๆ ModelState.Remove คือ .. มีปัญหา .. เพราะถ้าคุณใช้ตัวช่วยคุณจะไม่รู้ชื่อจริงๆ (เว้นแต่คุณจะยึดตามหลักการตั้งชื่อ) เว้นแต่คุณจะสร้างฟังก์ชันที่ทั้งผู้ช่วยแบบกำหนดเองและตัวควบคุมของคุณสามารถใช้เพื่อตั้งชื่อได้

คุณลักษณะนี้ควรได้รับการใช้งานเป็นตัวเลือกบนตัวช่วยโดยที่โดยค่าเริ่มต้นจะไม่ทำเช่นนี้ แต่ถ้าคุณต้องการให้ข้อมูลที่ไม่ได้รับการยอมรับแสดงอีกครั้งคุณสามารถพูดได้

แต่อย่างน้อยฉันก็เข้าใจปัญหาตอนนี้;)


ฉันต้องทำแบบนี้ ดูวิธีการของฉันที่ฉันโพสต์ไว้ด้านล่างซึ่งช่วยให้ฉันได้Remove()คีย์ที่ถูกต้อง
Tobias J

0

รับทราบในตอนท้าย Custom ModelBinder ของฉันซึ่งไม่ได้ลงทะเบียนและทำสิ่งนี้:

var mymsPage = new MyCmsPage();

NameValueCollection frm = controllerContext.HttpContext.Request.Form;

myCmsPage.SeoTitle = (!String.IsNullOrEmpty(frm["seoTitle"])) ? frm["seoTitle"] : null;

ดังนั้นสิ่งที่การเชื่อมโมเดลเริ่มต้นกำลังทำอยู่ต้องทำให้เกิดปัญหา ไม่แน่ใจว่าอะไร แต่อย่างน้อยปัญหาของฉันได้รับการแก้ไขแล้วตอนนี้ตัวประสานโมเดลที่กำหนดเองของฉันกำลังได้รับการลงทะเบียน


ฉันไม่มีประสบการณ์กับ ModelBinder ที่กำหนดเองค่าเริ่มต้นนั้นเหมาะกับความต้องการของฉันจนถึงตอนนี้ =)
JOBG

0

โดยทั่วไปเมื่อคุณพบว่าตัวเองกำลังต่อสู้กับแนวปฏิบัติมาตรฐานของกรอบการทำงานก็ถึงเวลาที่ต้องพิจารณาแนวทางของคุณใหม่ ในกรณีนี้พฤติกรรมของ ModelState ตัวอย่างเช่นเมื่อคุณไม่ต้องการสถานะโมเดลหลังจาก POST ให้พิจารณาการเปลี่ยนเส้นทางไปที่ get

[HttpPost]
public ActionResult Edit(MyCmsPage page, string submitButton)
{
    if (ModelState.IsValid) {
        SomeRepository.SaveChanges(page);
        return RedirectToAction("GenerateSeoTitle",new { page.Id });
    }
    return View(page);
}

public ActionResult GenerateSeoTitle(int id) {
     var page = SomeRepository.Find(id);
     page.GenerateSeoTitle();
     return View("Edit",page);
}

แก้ไขเพื่อตอบความคิดเห็นเกี่ยวกับวัฒนธรรม:

นี่คือสิ่งที่ฉันใช้เพื่อจัดการกับแอปพลิเคชัน MVC ที่มีหลายวัฒนธรรม อันดับแรกคลาสย่อยของตัวจัดการเส้นทาง:

public class SingleCultureMvcRouteHandler : MvcRouteHandler {
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        var culture = requestContext.RouteData.Values["culture"].ToString();
        if (string.IsNullOrWhiteSpace(culture))
        {
            culture = "en";
        }
        var ci = new CultureInfo(culture);
        Thread.CurrentThread.CurrentUICulture = ci;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
        return base.GetHttpHandler(requestContext);
    }
}

public class MultiCultureMvcRouteHandler : MvcRouteHandler
{
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        var culture = requestContext.RouteData.Values["culture"].ToString();
        if (string.IsNullOrWhiteSpace(culture))
        {
            culture = "en";
        }
        var ci = new CultureInfo(culture);
        Thread.CurrentThread.CurrentUICulture = ci;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
        return base.GetHttpHandler(requestContext);
    }
}

public class CultureConstraint : IRouteConstraint
{
    private string[] _values;
    public CultureConstraint(params string[] values)
    {
        this._values = values;
    }

    public bool Match(HttpContextBase httpContext,Route route,string parameterName,
                        RouteValueDictionary values, RouteDirection routeDirection)
    {

        // Get the value called "parameterName" from the 
        // RouteValueDictionary called "value"
        string value = values[parameterName].ToString();
        // Return true is the list of allowed values contains 
        // this value.
        return _values.Contains(value);

    }

}

public enum Culture
{
    es = 2,
    en = 1
}

และนี่คือวิธีการเชื่อมต่อเส้นทาง หลังจากสร้างเส้นทางแล้วฉันจะนำหน้าซับเอเจนต์ของฉัน (example.com/subagent1, example.com/subagent2 เป็นต้น) ตามด้วยรหัสวัฒนธรรม หากสิ่งที่คุณต้องการคือวัฒนธรรมเพียงแค่ลบซับเอเจนต์ออกจากตัวจัดการเส้นทางและเส้นทาง

    public static void RegisterRoutes(RouteCollection routes)
    {

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.IgnoreRoute("Content/{*pathInfo}");
        routes.IgnoreRoute("Cache/{*pathInfo}");
        routes.IgnoreRoute("Scripts/{pathInfo}.js");
        routes.IgnoreRoute("favicon.ico");
        routes.IgnoreRoute("apple-touch-icon.png");
        routes.IgnoreRoute("apple-touch-icon-precomposed.png");

        /* Dynamically generated robots.txt */
        routes.MapRoute(
            "Robots.txt", "robots.txt",
            new { controller = "Robots", action = "Index", id = UrlParameter.Optional }
        );

        routes.MapRoute(
             "Sitemap", // Route name
             "{subagent}/sitemap.xml", // URL with parameters
             new { subagent = "aq", controller = "Default", action = "Sitemap"},  new[] { "aq3.Controllers" } // Parameter defaults
        );

        routes.MapRoute(
             "Rss Feed", // Route name
             "{subagent}/rss", // URL with parameters
             new { subagent = "aq", controller = "Default", action = "RSS"},  new[] { "aq3.Controllers" } // Parameter defaults
        );

        /* remap wordpress tags to mvc blog posts */
        routes.MapRoute(
            "Tag", "tag/{title}",
            new { subagent = "aq", controller = "Default", action = "ThreeOhOne", id = UrlParameter.Optional},  new[] { "aq3.Controllers" }
        ).RouteHandler = new MultiCultureMvcRouteHandler(); ;

        routes.MapRoute(
            "Custom Errors", "Error/{*errorType}",
            new { controller = "Error", action = "Index", id = UrlParameter.Optional},  new[] { "aq3.Controllers" }
        );

        /* dynamic images not loaded from content folder */
        routes.MapRoute(
            "Stock Images",
            "{subagent}/Images/{*filename}",
            new { subagent = "aq", controller = "Image", action = "Show", id = UrlParameter.Optional, culture = "en"},  new[] { "aq3.Controllers" }
        );

        /* localized routes follow */
        routes.MapRoute(
            "Localized Images",
            "Images/{*filename}",
            new { subagent = "aq", controller = "Image", action = "Show", id = UrlParameter.Optional},  new[] { "aq3.Controllers" }
        ).RouteHandler = new MultiCultureMvcRouteHandler();

        routes.MapRoute(
            "Blog Posts",
            "Blog/{*postname}",
            new { subagent = "aq", controller = "Blog", action = "Index", id = UrlParameter.Optional},  new[] { "aq3.Controllers" }
        ).RouteHandler = new MultiCultureMvcRouteHandler();

        routes.MapRoute(
            "Office Posts",
            "Office/{*address}",
            new { subagent = "aq", controller = "Offices", action = "Address", id = UrlParameter.Optional }, new[] { "aq3.Controllers" }
        ).RouteHandler = new MultiCultureMvcRouteHandler();

        routes.MapRoute(
             "Default", // Route name
             "{controller}/{action}/{id}", // URL with parameters
             new { subagent = "aq", controller = "Home", action = "Index", id = UrlParameter.Optional }, new[] { "aq3.Controllers" } // Parameter defaults
        ).RouteHandler = new MultiCultureMvcRouteHandler();

        foreach (System.Web.Routing.Route r in routes)
        {
            if (r.RouteHandler is MultiCultureMvcRouteHandler)
            {
                r.Url = "{subagent}/{culture}/" + r.Url;
                //Adding default culture 
                if (r.Defaults == null)
                {
                    r.Defaults = new RouteValueDictionary();
                }
                r.Defaults.Add("culture", Culture.en.ToString());

                //Adding constraint for culture param
                if (r.Constraints == null)
                {
                    r.Constraints = new RouteValueDictionary();
                }
                r.Constraints.Add("culture", new CultureConstraint(Culture.en.ToString(), Culture.es.ToString()));
            }
        }

    }

คุณพูดถูกมากที่แนะนำวิธีปฏิบัติ POST REDIRECT อันที่จริงฉันทำแบบนี้เกือบทุกการโพสต์ อย่างไรก็ตามฉันมีความต้องการเป็นพิเศษ: ฉันมีแบบฟอร์มตัวกรองที่ด้านบนของหน้าซึ่งในตอนแรกจะส่งมาพร้อมกับ get แต่ฉันพบปัญหาเกี่ยวกับช่องวันที่ไม่ถูกผูกมัดและจากนั้นก็พบว่าคำขอ GET ไม่ได้มีวัฒนธรรมอยู่ (ฉันใช้ภาษาฝรั่งเศสสำหรับแอปของฉัน) ดังนั้นฉันจึงต้องเปลี่ยนคำขอเป็น POST เพื่อผูกวันที่ของฉันได้สำเร็จ แล้วปัญหานี้มาฉันติดเธอนิดหน่อย ..
Souhaieb Besbes

@SouhaiebBesbes ดูการอัปเดตของฉันที่แสดงให้เห็นว่าฉันจัดการกับวัฒนธรรมอย่างไร
B2K

@SouhaiebBesbes บางทีการจัดเก็บวัฒนธรรมของคุณใน TempData จะง่ายกว่าเล็กน้อย ดูstackoverflow.com/questions/12422930/…
B2K

0

ดูเหมือนว่าสิ่งนี้จะใช้ได้กับ Razor Page ของฉันและไม่เคยแม้แต่จะเดินทางไปยังไฟล์. cs นี่เป็นวิธี html แบบเก่า มันอาจมีประโยชน์

<input type="reset" value="Reset">
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.