การเข้าถึงคุณสมบัติของ MVC จาก Javascript


147

ฉันมีโมเดลต่อไปนี้ซึ่งรวมอยู่ในโมเดลมุมมองของฉัน

public class FloorPlanSettingsModel
{
    public int Id { get; set; }
    public int? MainFloorPlanId { get; set; }
    public string ImageDirectory { get; set; }
    public string ThumbnailDirectory { get; set; }
    public string IconsDirectory { get; set; }
}

ฉันจะเข้าถึงหนึ่งในคุณสมบัติข้างต้นจาก Javascript ได้อย่างไร

ฉันลองสิ่งนี้ แต่ได้ "ไม่ได้กำหนด"

var floorplanSettings = "@Model.FloorPlanSettings";
alert(floorplanSettings.IconsDirectory);

5
สิ่งที่เกิดขึ้นคือคุณกำลังตั้งค่าตัวแปร JavaScript เป็นค่าของตัวแปร C # "Model.FloorPlanSettings" ซึ่งจะเป็นค่า. ToString () ของคลาสนั้น (สตริง) จากนั้นคุณพยายามแจ้งเตือนคุณสมบัติ JavaScript ที่เรียกว่า "IconsDirectory" บนตัวแปรสตริง JavaScript ที่คุณเพิ่งสร้างขึ้น คุณไม่ได้กำหนดเนื่องจากสตริง JavaScript ไม่มีคุณสมบัติ "IconsDirectory"
Joel Cochran

ให้กรณีทดสอบที่สมบูรณ์และอธิบายสถานการณ์ทั้งหมดของการกำหนด Model data ให้กับตัวแปร javascript
Rajshekar Reddy

สิ่งนี้ไม่ทำงานนอกมุมมอง (cshtml) เช่นในไฟล์. js ภายนอกที่อ้างอิงโดยมุมมอง
Spencer Sullivan

คำตอบ:


240

คุณสามารถนำโมเดลฝั่งเซิร์ฟเวอร์ทั้งหมดของคุณและเปลี่ยนเป็นวัตถุ Javascript โดยทำสิ่งต่อไปนี้:

var model = @Html.Raw(Json.Encode(Model));

ในกรณีของคุณถ้าคุณต้องการให้วัตถุ FloorSetSettings ผ่านEncodeวิธีการที่คุณสมบัติ:

var floorplanSettings = @Html.Raw(Json.Encode(Model.FloorPlanSettings));

1
เพียงยืนยันไม่จำเป็นต้องเพิ่ม; ในตอนท้ายของมันได้หรือไม่ เนื่องจากฉันได้รับพรอมต์จาก VS ที่ระบุว่าคำสั่งไม่ได้ถูกยกเลิก แต่เมื่อฉันพยายามเพิ่ม; รหัสไม่ทำงาน
การอ้างอิง Null

1
คุณรู้อะไรฉันได้รับข้อผิดพลาดเดียวกันในโครงการต่าง ๆ ของฉันเช่นกัน เพียงไม่สนใจมัน มันเป็น Visual Studio พยายามช่วย แต่มันผิดในกรณีนี้ HTML และสคริปต์ที่เป็นผลลัพธ์ที่ส่งไปยังเบราว์เซอร์นั้นถูกต้อง
Justin Helgerson

1
สำหรับฉันสิ่งนี้ทำงานได้: var myModel = @ {@ Html.Raw (Json.Encode (Model));}
ซ่อน

1
ไม่ทำงานหากรูปแบบเป็นค่าเริ่มต้น (สร้างหน้าแทนหน้าแก้ไข) และ "ReferenceError: ไม่ได้กำหนดรุ่น"
แจ็ค

2
ใน ASP.Net Core, Json.Serialize ()
Mohammed Noureldin

131

เนื้อหาของคำตอบ

1) วิธีเข้าถึงข้อมูลโมเดลใน Javascript / Jquery code block ใน.cshtmlไฟล์

2) วิธีเข้าถึงข้อมูลโมเดลใน Javascript / Jquery code block ใน.jsไฟล์

วิธีเข้าถึงข้อมูลโมเดลใน Javascript / Jquery code block ใน.cshtmlไฟล์

ตัวแปร c # มีสองประเภทที่Modelกำหนดให้กับตัวแปร JavaScript

  1. ที่ได้รับมอบหมายคุณสมบัติ - ประเภทข้อมูลพื้นฐานเช่นint, string, DateTime(เช่น: Model.Name)
  2. การกำหนดวัตถุ - คลาสที่กำหนดเองหรือคลาส inbuilt (เช่น: Model, Model.UserSettingsObj)

ให้ดูรายละเอียดของการบ้านทั้งสองนี้

สำหรับส่วนที่เหลือของคำตอบให้พิจารณาตัวอย่างด้านล่างAppUserเป็นตัวอย่าง

public class AppUser
{
    public string Name { get; set; }
    public bool IsAuthenticated { get; set; }
    public DateTime LoginDateTime { get; set; }
    public int Age { get; set; }
    public string UserIconHTML { get; set; }
}

และค่าที่เรากำหนดให้โมเดลนี้คือ

AppUser appUser = new AppUser
{
    Name = "Raj",
    IsAuthenticated = true,
    LoginDateTime = DateTime.Now,
    Age = 26,
    UserIconHTML = "<i class='fa fa-users'></i>"
};

การมอบหมายคุณสมบัติ

ให้ใช้ไวยากรณ์ที่แตกต่างกันสำหรับการกำหนดและสังเกตผลลัพธ์

1)ไม่มีการตัดการกำหนดคุณสมบัติในเครื่องหมายคำพูด

var Name = @Model.Name;  
var Age = @Model.Age;
var LoginTime = @Model.LoginDateTime; 
var IsAuthenticated = @Model.IsAuthenticated;   
var IconHtml = @Model.UserIconHTML;  

ป้อนคำอธิบายรูปภาพที่นี่

อย่างที่คุณเห็นมีข้อผิดพลาดสองสามข้อRajและTrueถือเป็นตัวแปรจาวาสคริปต์และเนื่องจากไม่มีvariable undefinedข้อผิดพลาดเกิดขึ้น โดยที่สำหรับวันที่และเวลาที่หลากหลายข้อผิดพลาดคือunexpected numberตัวเลขไม่สามารถมีอักขระพิเศษได้แท็ก HTML จะถูกแปลงเป็นชื่อเอนทิตีเพื่อเบราว์เซอร์จะไม่รวมค่าของคุณและมาร์กอัป HTML

2) การกำหนดคุณสมบัติในการห่อคำพูด

var Name = '@Model.Name';
var Age = '@Model.Age';
var LoginTime = '@Model.LoginDateTime';
var IsAuthenticated = '@Model.IsAuthenticated';
var IconHtml = '@Model.UserIconHTML'; 

ป้อนคำอธิบายรูปภาพที่นี่

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

3)ใช้@Html.Rawแต่ไม่ต้องหุ้มมันด้วยเครื่องหมายคำพูด

 var Name = @Html.Raw(Model.Name);
 var Age = @Html.Raw(Model.Age);
 var LoginTime = @Html.Raw(Model.LoginDateTime);
 var IsAuthenticated = @Html.Raw(Model.IsAuthenticated);
 var IconHtml = @Html.Raw(Model.UserIconHTML);

ป้อนคำอธิบายรูปภาพที่นี่

ผลลัพธ์คล้ายกับกรณีทดสอบของเรา 1 อย่างไรก็ตามการใช้งาน@Html.Raw()บนHTMLสายอักขระแสดงการเปลี่ยนแปลงบางอย่างแก่เรา HTML จะถูกรักษาไว้โดยไม่เปลี่ยนเป็นชื่อเอนทิตี

จากเอกสารHtml.Raw ()

ห่อมาร์กอัพ HTML ในอินสแตนซ์ HtmlString เพื่อให้ตีความเป็นมาร์กอัพ HTML

แต่ก็ยังมีข้อผิดพลาดในบรรทัดอื่น

4)การใช้@Html.Rawและการห่อด้วยคำพูด

var Name ='@Html.Raw(Model.Name)';
var Age = '@Html.Raw(Model.Age)';
var LoginTime = '@Html.Raw(Model.LoginDateTime)';
var IsAuthenticated = '@Html.Raw(Model.IsAuthenticated)';
var IconHtml = '@Html.Raw(Model.UserIconHTML)';

ป้อนคำอธิบายรูปภาพที่นี่

ผลลัพธ์ที่ดีกับทุกประเภท แต่HTMLตอนนี้ข้อมูลของเราเสียและสิ่งนี้จะทำให้สคริปต์เสียหาย ปัญหานี้เกิดขึ้นเนื่องจากเรากำลังใช้เครื่องหมายคำพูดเดี่ยว'เพื่อตัดข้อมูลและแม้แต่ข้อมูลที่มีเครื่องหมายคำพูดเดี่ยว

เราสามารถเอาชนะปัญหานี้ได้ 2 วิธี

1) ใช้เครื่องหมายคำพูดคู่" "เพื่อตัดส่วน HTML เนื่องจากข้อมูลภายในมีเครื่องหมายคำพูดเดียวเท่านั้น (ตรวจสอบให้แน่ใจว่าหลังจากห่อด้วยเครื่องหมายคำพูดคู่ไม่มี"อยู่ในข้อมูลด้วย)

  var IconHtml = "@Html.Raw(Model.UserIconHTML)";

2) หลีกเลี่ยงความหมายของตัวละครในโค้ดฝั่งเซิร์ฟเวอร์ของคุณ ชอบ

  UserIconHTML = "<i class=\"fa fa-users\"></i>"

บทสรุปของการกำหนดคุณสมบัติ

  • ใช้เครื่องหมายคำพูดสำหรับ dataType ที่ไม่ใช่ตัวเลข
  • ห้ามใช้เครื่องหมายคำพูดสำหรับ dataType ที่เป็นตัวเลข
  • ใช้Html.Rawเพื่อตีความข้อมูล HTML ของคุณตามที่เป็นอยู่
  • ดูแลข้อมูล HTML ของคุณเพื่อหลีกเลี่ยงความหมายของคำพูดในฝั่งเซิร์ฟเวอร์หรือใช้คำพูดที่แตกต่างจากข้อมูลในระหว่างการกำหนดตัวแปร javascript

การกำหนดวัตถุ

ให้ใช้ไวยากรณ์ที่แตกต่างกันสำหรับการกำหนดและสังเกตผลลัพธ์

1)ไม่มีการกำหนดวัตถุในคำพูด

  var userObj = @Model; 

ป้อนคำอธิบายรูปภาพที่นี่

เมื่อคุณกำหนด ac # object ให้กับตัวแปร javascript ค่าของการ.ToString()oject นั้นจะถูกกำหนด ดังนั้นผลลัพธ์ข้างต้น

2 การตัดการกำหนดวัตถุในเครื่องหมายคำพูด

var userObj = '@Model'; 

ป้อนคำอธิบายรูปภาพที่นี่

3)การใช้Html.Rawโดยไม่ต้องใส่เครื่องหมายคำพูด

   var userObj = @Html.Raw(Model); 

ป้อนคำอธิบายรูปภาพที่นี่

4)ใช้Html.Rawพร้อมกับคำพูด

   var userObj = '@Html.Raw(Model)'; 

ป้อนคำอธิบายรูปภาพที่นี่

Html.Rawเป็นของไม่มีประโยชน์มากสำหรับเราในขณะที่การกำหนดวัตถุให้กับตัวแปร

5)การใช้Json.Encode()โดยไม่ต้องใส่เครื่องหมายคำพูด

var userObj = @Json.Encode(Model); 

//result is like
var userObj = {&quot;Name&quot;:&quot;Raj&quot;,
               &quot;IsAuthenticated&quot;:true,
               &quot;LoginDateTime&quot;:&quot;\/Date(1482572875150)\/&quot;,
               &quot;Age&quot;:26,
               &quot;UserIconHTML&quot;:&quot;\u003ci class=\&quot;fa fa-users\&quot;\u003e\u003c/i\u003e&quot;
              };

เราเห็นการเปลี่ยนแปลงบ้างเราเห็นว่าโมเดลของเรากำลังถูกตีความว่าเป็นวัตถุ entity namesแต่เราได้อักขระพิเศษเหล่านั้นเปลี่ยนไป การรวมไวยากรณ์ข้างต้นในเครื่องหมายคำพูดนั้นไม่มีประโยชน์อะไร เราเพียงรับผลลัพธ์เดียวกันภายในเครื่องหมายคำพูด

จากเอกสารของJson.Encode ()

แปลงออบเจ็กต์ข้อมูลเป็นสตริงที่อยู่ในรูปแบบ JavaScript Object Notation (JSON)

ในขณะที่คุณได้พบนี้แล้วปัญหาที่มีการกำหนดคุณสมบัติและหากคุณจำได้ว่าเราเอาชนะมันด้วยการใช้งานของentity Name Html.Rawลองทำดูสิ ให้รวมกันHtml.RawและJson.Encode

6)การใช้Html.RawและJson.Encodeไม่ใส่เครื่องหมายคำพูด

var userObj = @Html.Raw(Json.Encode(Model));

ผลลัพธ์เป็นวัตถุ Javascript ที่ถูกต้อง

 var userObj = {"Name":"Raj",
     "IsAuthenticated":true,
     "LoginDateTime":"\/Date(1482573224421)\/",
     "Age":26,
     "UserIconHTML":"\u003ci class=\"fa fa-users\"\u003e\u003c/i\u003e"
 };

ป้อนคำอธิบายรูปภาพที่นี่

7)การใช้Html.RawและJson.Encodeภายในเครื่องหมายคำพูด

var userObj = '@Html.Raw(Json.Encode(Model))';

ป้อนคำอธิบายรูปภาพที่นี่

ตามที่คุณเห็นการตัดคำพูดให้ข้อมูล JSONแก่เรา

ข้อ จำกัด ในการมอบหมายวัตถุ

  • การใช้งานHtml.RawและJson.Encodeใน combintaion เพื่อกำหนดวัตถุของคุณให้กับตัวแปรจาวาสคริปต์เป็นวัตถุ JavaScript
  • ใช้Html.RawและJson.Encodeตัดมันภายในquotesเพื่อรับJSON

หมายเหตุ:หากคุณสังเกตว่ารูปแบบข้อมูล DataTime ไม่ถูกต้อง นี่เป็นเพราะที่ได้กล่าวไปแล้วก่อนหน้านี้Converts a data object to a string that is in the JavaScript Object Notation (JSON) formatและ JSON ไม่มีdateประเภท ตัวเลือกอื่น ๆ ในการแก้ไขปัญหานี้คือการเพิ่มบรรทัดของรหัสอื่นเพื่อจัดการกับชนิดนี้เพียงอย่างเดียวโดยใช้วันที่ javascipt ()วัตถุ

var userObj.LoginDateTime = new Date('@Html.Raw(Model.LoginDateTime)'); 
//without Json.Encode


วิธีเข้าถึงข้อมูลโมเดลใน Javascript / Jquery code block ใน.jsไฟล์

ไวยากรณ์ของมีดโกนไม่มีความหมายใน.jsไฟล์และด้วยเหตุนี้เราจึงไม่สามารถใช้โมเดลของเราเพื่อแทรก.jsไฟล์ได้ อย่างไรก็ตามมีวิธีแก้ไขเฉพาะหน้า

1)การแก้ปัญหาคือการใช้ตัวแปร JavaScript ทั่วโลก

เราต้องกำหนดค่าให้กับตัวแปร javascipt ที่มีขอบเขตทั่วโลกจากนั้นใช้ตัวแปรนี้ภายในบล็อคโค้ดทั้งหมดของคุณ.cshtmlและ.jsไฟล์ ดังนั้นไวยากรณ์จะเป็น

<script type="text/javascript">
  var userObj = @Html.Raw(Json.Encode(Model)); //For javascript object
  var userJsonObj = '@Html.Raw(Json.Encode(Model))'; //For json data
</script>

ด้วยสิ่งนี้เราสามารถใช้ตัวแปรuserObjและuserJsonObjเป็นและเมื่อจำเป็น

หมายเหตุ:ฉันเองไม่แนะนำให้ใช้ตัวแปรทั่วโลกเพราะมันยากสำหรับการบำรุงรักษา แต่ถ้าคุณไม่มีตัวเลือกอื่น ๆ แล้วคุณสามารถใช้มันกับมีการประชุมตั้งชื่อที่เหมาะสม .. userAppDetails_globalสิ่งที่ต้องการ

2)การใช้function ()หรือclosure ตัดรหัสทั้งหมดที่ขึ้นอยู่กับข้อมูลรุ่นในฟังก์ชั่น จากนั้นเรียกใช้ฟังก์ชันนี้จาก.cshtmlไฟล์

external.js

 function userDataDependent(userObj){
  //.... related code
 }

.cshtml ไฟล์

 <script type="text/javascript">
  userDataDependent(@Html.Raw(Json.Encode(Model))); //execute the function     
</script>

หมายเหตุ:ไฟล์ภายนอกของคุณจะต้องอ้างอิงก่อนสคริปต์ด้านบน มิฉะนั้นuserDataDependentฟังก์ชั่นจะไม่ได้กำหนด

โปรดทราบว่าฟังก์ชั่นจะต้องอยู่ในขอบเขตส่วนกลางด้วย ดังนั้นวิธีการแก้ปัญหาเราต้องจัดการกับผู้เล่นระดับโลก


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

@Snortnoun ใช่คุณสามารถทำได้คุณสามารถส่งคืนข้อมูลที่แก้ไขแล้วจากแบบฟอร์มหรือหากคุณไม่ต้องการโหลดหน้าซ้ำคุณสามารถใช้ AJAX ได้
Rajshekar Reddy

ฉันไม่ได้ใช้ ajax และพยายามแก้ไขโมเดลคุณสมบัติใน javascript แต่ในการส่งแบบฟอร์มการเปลี่ยนแปลงนี้ไม่ได้แสดงในแบบจำลอง ฉันกำลังทำสิ่งที่ชอบ: var model = @ Html.Raw (Json.Encode (Model)); model.EventCommand = "updatedvalue"; มันทำให้ฉันแบบถูกต้องและปรับปรุงค่า แต่ในการส่งการเปลี่ยนแปลงหายไปในวิธีการดำเนินการ (แม้ว่าฉันจะทำสิ่งเดียวกันโดยใช้การควบคุม Html ที่ซ่อนอยู่และผูกไว้กับ EventCommand และอัปเดตค่าเป็นจาวาสคริปต์ แต่สงสัยว่าถ้าทำแบบเดียวกันกับรุ่นโดยตรงได้ไหม)

@Snortnoun ฉันได้รับจุดของคุณแล้วvar model = @Html.Raw(Json.Encode(Model));สิ่งนี้จะสร้างวัตถุจาวาสคริปต์ modelที่ไม่มีส่วนเกี่ยวข้องกับโมเดล C # ซึ่งคุณส่งผ่านไปยังมุมมอง Infact จะไม่มีModelหลังจากแสดงผลแล้ว ดังนั้นรูปแบบใน UI จะไม่มีเงื่อนงำในการเปลี่ยนแปลงข้อมูลวัตถุจาวาสคริปต์ ตอนนี้คุณต้องส่งแบบจำลองที่แก้ไขทั้งหมดนี้ไปยังคอนโทรลเลอร์ผ่าน AJAX หรือคุณต้องอัปเดตค่าของการควบคุมอินพุตของคุณด้วยในรูปแบบโดยใช้จาวาสคริปต์
Rajshekar Reddy

Although I did the same thing using hidden Html control and bound it to EventCommand and updated it's value in javascript. But wondering if could do same directly to model?สำหรับคำสั่งนี้ .. ไม่มีEventCommand ใน MVC สำหรับ Webforms ที่มีการเชื่อมต่อระหว่าง UI และการกระทำของเซิร์ฟเวอร์ใน MVC แยกออกทั้งหมด วิธีเดียวที่คุณจะโต้ตอบกับคอนโทรลเลอร์ทำได้ผ่าน AJAX หรือส่งแบบฟอร์มหรือขอหน้าใหม่ (โหลดซ้ำ)
Rajshekar Reddy

21

ลองนี้: (คุณพลาดคำพูดเดียว)

var floorplanSettings = '@Html.Raw(Json.Encode(Model.FloorPlanSettings))';

1
@JuanPieterse ด้วยคำพูดช่วยให้คุณมีJSONคำพูด wihtout javascript Objectจะช่วยให้คุณ ตรวจสอบคำตอบของฉันในหัวข้อเดียวกันสำหรับรายละเอียดเพิ่มเติม stackoverflow.com/a/41312348/2592042
Rajshekar Reddy

นั่นไม่เป็นความจริง @danmbuen แก้ปัญหาทำงานในกรณีของฉันฉันมีปัญหาและห่อระหว่างคำพูดเดียวทำงานเหมือนมีเสน่ห์ THANK YOU;)
Dimitri

4

การห่อตัวแบบจำลองรอบ ๆ parens ใช้งานได้สำหรับฉัน คุณยังคงได้รับปัญหาเดียวกันกับ Visual Studio ที่บ่นเกี่ยวกับเซมิโคลอน แต่ทำงานได้

var closedStatusId = @(Model.ClosedStatusId);

0

หากมีการยกข้อผิดพลาด"ReferenceError: Model ไม่ได้กำหนดไว้"คุณอาจลองใช้วิธีการต่อไปนี้:

$(document).ready(function () {

    @{  var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
         var json = serializer.Serialize(Model);
    }

    var model = @Html.Raw(json);
    if(model != null && @Html.Raw(json) != "undefined")
    {
        var id= model.Id;
        var mainFloorPlanId = model.MainFloorPlanId ;
        var imageDirectory = model.ImageDirectory ;
        var iconsDirectory = model.IconsDirectory ;
    }
});

หวังว่านี่จะช่วย ...


0

ฉันรู้ว่ามันสายเกินไป แต่วิธีนี้ใช้ได้ดีทั้ง. net framework และ. net core:

@ System.Web.HttpUtility.JavaScriptStringEncode ()

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