iT邦幫忙

0

實作帶入值 - 詢問值從Controller與Model帶回View方式

想了解MVC的完整從後端將值填回頁面上的方式,所以現在嘗試在View上按下button後,然後在Controller寫定一個值以後,再帶回View的textbox上,但我目前實作不出來,請問哪裡要做調整呢?

【View】

@model Practice.Models.TestModel

@{
    ViewBag.Title = "Home";
}

<html>
<head>
    <title></title>
</head>
<body>
<div class="row">
        <div class="col-md-4">
            <br />
            <label>取得Name : </label>
        </div>
    </div>
    <div class="row">
        <div class="col-md-4">
            Name:@Html.TextBoxFor(m => m.Name)
            <input type="button" id="sName" value="" onclick="GetName()" />
        </div>
    </div>

</body>
</html>

【Controller】

@model Practice.Models.TestModel

namespace Practice.Controllers
{
    public class TestController : Controller
    {
    
        public ActionResult TestIndex()
        {
            return View();
        }
        
        protected void GetName()
        {
            var sName="testName"
            TestModel objModel = new TestModel();
            objModel.Name = sName;

            return;
        }
        
    }
}

【Model】

namespace Practice.Models
{
    public class TestModel
    {
        public string Name { get; set; }
    }
}

2 個回答

2
YoChen
iT邦研究生 5 級 ‧ 2020-11-25 13:51:29
最佳解答

依照您目前的需求,搭配Ajax來實作應該比較簡單一點。
然後,您可能要注意一下前、後端語法混用的問題~XDDD

首先,要使用Ajax就必須先將對應的API先建出來

// Controller
public ActionResult GetName() 
{
    return Content("YoChen");
}

接著,準備好HTML (我只列出必要的Tag)

<!-- View -->
<input type="text" id="display" value="" />
<input type="button" id="getNameButton" value="Get Name!!" />

最後,我們來Call API (MVC預設有引用Jquery,這邊就直接用Jquery了~XDDD)

$(function () {
    $('#getNameButton').click(function () {
        $.ajax(
            "/Test/GetName",
            {
                success: function (data, textStatus, jqXHR) {
                    $('#display').val(data);
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    console.log(errorThrown);
                }
            }
        )
    })
}
看更多先前的回應...收起先前的回應...
cucat iT邦新手 5 級 ‧ 2020-11-25 15:09:27 檢舉

瞭解~
不過因為想要實際瞭解MVC怎麼跑的,所以用的最簡單的方式,然後讓Model、View、Controller裡面都有作用,不知道若是這樣的話,請問可以怎麼調整呢?

YoChen iT邦研究生 5 級 ‧ 2020-11-25 16:34:44 檢舉

不免俗地還是要提醒您,MVC只是一種架構模式,並非所有使用者行為都一定會接觸到M、V、C哦!! XDDD

觀察流程,可以參考以下程式碼

// Model
public class TestViewModel
{
    public string Name { get; set; }
}
// Controller
public ActionResult Index()
{
    TestViewModel model = new TestViewModel() { Name = "YoChen" };
    return View(model);
}
<!-- View -->
@model Practice.Models.TestViewModel
<h1>@Model.Name</h1>
cucat iT邦新手 5 級 ‧ 2020-11-27 14:22:08 檢舉

好的,我知道,只是想透過這個簡單的練習瞭解 MVC 架構~

目前有個問題,就是我想透過按鈕事件將值帶出來,那這樣的話在Controller感覺要放在其他ActionResult中,但我目前調整成如下,並不會做動,請問可以怎麼調整呢,謝謝您!

<!-- View 以下兩個寫法不知道怎麼放才對 -->

Name:<input type="text" id="sName" value=@Model.Name readonly="readonly" />

Name:@Html.TextBoxFor(m => m.Name)
<input type="button" id="sName" onclick="@Url.Action("GetName", "TestController")" />
// Controller
public string GetName()
{
    var _name="YoChen";
    TestViewModel model = new TestViewModel() { _name };
    return View(model);
}
// Model
public class TestViewModel
{
    public string Name { get; set; }
}
YoChen iT邦研究生 5 級 ‧ 2020-11-27 16:11:21 檢舉
  1. 要注意在處理HTML Attribute的時候,"(引號)不要遺漏。
    不過這部分Browser應該有能力自行除錯,
    如果開啟開發者工具以後發現"(引號)的部分沒有問題的話,
    可能需要檢查看看Model.Name是否有賦值
    或是看看Action是否有將Model帶入View當中
<!--value缺乏引號-->
Name:<input type="text" id="sName" value=@Model.Name readonly="readonly" /> 

<!--調整為-->
Name:<input type="text" id="sName" value="@(Model.Name)" readonly="readonly" />
  1. onclick Attribute內部應該放的是javascript的functionUrl.Action只能輸出對應Action的Url
<!--onclick未給予function-->
<input type="button" id="sName" onclick='@Url.Action("GetName", "TestController")' />

<!--調整為-->
<input type="button" id="sName" onclick="CallMyNameAPI()" />
<script>
function CallMyNameAPI() {
    $.ajax(
        '@Url.Action("GetName", "Test")',
        {
            success: function (data, textStatus, jqXHR) {
                $('#Name').val(data);
            },
            error: function (jqXHR, textStatus, errorThrown) {
                console.log(errorThrown);
            }
        }
    )
}
</script>
2
japhenchen
iT邦大師 1 級 ‧ 2020-11-26 00:23:50

我的思路跟各大神們不太一樣

單從MVC跟ajax來比,我還比較喜歡用ajax來的直觀點,至少不會有轉來轉去的搞到昏頭的麻煩

舉我最近在做的專案為例
後端 C#

    dcERPDataContext myERP = new dcERPDataContext();
    protected void Page_Load(object sender, EventArgs e)
    {
        string pono = Request.Form["pono"];
        string act = Request.Form["act"];
        if (act == "getPO" && !string.IsNullOrEmpty(pono))
        {
            getPO(pono.Trim().ToUpper());
        }
    }

    private void getPO(string pono)
    {
        //用linq抓資料並直接轉json
        var data = (from m in myERP.POMaster
                    join d  in myERP.PODetail on m.id equals d.Mainid into detail
                    join c in myERP.Emp on m.empid equals c.id into contactor
                    where m.no == pono.ToUpper()
                    select new { 
                        m, 
                        detail=detail.OrderBy(o=>o.id)
                        ,contactor 
                    }).ToArray();
        Response.Clear();
        Response.Write(JsonConvert.SerializeObject(data).Replace("null","\"\""));
        //上面那行防止出現null字樣,一律換成空字串....偷吃步
        Response.End();
    }

前端的javascript(我慣用jQuery),至於HTML就簡單的跟什麼一樣..沒什麼好舉例

$(function () {
    let pono = "pono".urlParamValue();
    if (pono !== "") {
        getPO(pono);
    }
}
var getPO = function (po) { //用ajax把收到的json布置到網頁而已
    $.post({
        url: "./",
        dataType: "json",
        data: {
            act: "getPO",
            pono: po,
        }
    })
        .done(function (data) {
            //這裡沒什麼,自己手動佈置畫面而已,把json一一塞進畫面格子裡
            if (data.length > 0) {
                let master = data[0].m;
                let detail = data[0].detail;
                let contactor = data[0].contactor;
                $("#tbProject").val(master.ProjectNo);
                $("#tbProjectName").val(master.ProjectName);
                $("#tbPoNo").val(master.no);
                $("#tbWorkGroundContactor").val(master.contactor);
                if (contactor.length > 0) {                    $("#tbWorkGroundContactor").val(`${$("#tbWorkGroundContactor").val()} ${contactor[0].empname}`);
                }
                $("#tbPosMemo").val(master.memo);
                if (detail.length > 0) {
                    //塞表身,我不愛用table,用css table
                    detail.forEach(function (item) {
                        let tr = $(`<div class="tr trbody" id="${item.id}"></div>`);
                        tr.data('itemdata', item); //tr的data塞進整個array
                        tr.append($(`<div class="tdh td">${item.itemname}</div>`));
                        tr.append($(`<div class="tdh td">${item.price}</div>`));
                        // 以下省略1001行,都在塞格而已.....
                        $("#posdetail .datagrid").append(tr);
                    });
                    resizeDataGrid("#posdetail .datagrid"); // 把表格對齊
                }
            }
        })
        .fail(function (d) {
            //偷懶沒寫錯誤處理
        });
};

var resizeDataGrid = function (gridname) {
    // 上面提到表格對齊用的,偷吃步,我就不愛用Table..
    let thArr = $(`${gridname} .tr:first-child .th`);
    $(`${gridname} .tr:first-child .td`).each(function (i, v) {
        if ($(thArr).innerWidth() < $(v).outerWidth() - 1) {
            $(thArr[i]).innerWidth($(v).outerWidth() - 1);
        }
    });
};

//抓url後面的params用的prototype
String.prototype.urlParamValue = function () {
    var desiredVal = null;
    var paramName = this.valueOf();
    window.location.search.substring(1).split('&').some(function (currentValue, _, _) {
        var nameVal = currentValue.split('=');
        if (decodeURIComponent(nameVal[0]) === paramName) {
            desiredVal = decodeURIComponent(nameVal[1]);
            return true;
        }
        return false;
    });
    return desiredVal;
};

頁面的部份截圖(已馬)
https://ithelp.ithome.com.tw/upload/images/20201126/20117954PDZJmnMY17.png

真的後端完全不管HTML怎麼做,前端也不管資料庫到底長在什麼地方,哪天我爽,從mssql搬到postgresql,前端也不會需要任何改動

上例扯到太多工作上的東西所以有改很多,可能有的變數名沒改到,會有點亂七八糟,拜託.....砍小力一點

會有這個試算表,是因為有時採購的內容成百上千行,從頭把單價打到尾,還沒打完網路出問題,等於做白工,所以才弄了這個試算的功能,還給用戶有存草稿的機會,避免直接上線打一半斷線的鳥問題發作,那真的會被罵到臭頭..

cucat iT邦新手 5 級 ‧ 2020-11-27 14:09:01 檢舉

謝謝您~ 就像YoChen 回覆的一樣,這個方式經過兩位的演示,我有理解並實作出來,謝謝!

我要發表回答

立即登入回答