用JavaScript从视图调用Action方法

时间:2022-12-01 22:44:09

I am new to MVC and stuck with a problem. I have a view that allows users to select an item and then click on a button to view a report on that item. The report is a also an MVC View that expects it's model to be initialized. There is a controller action method to initialize the Model and call the report view.

我是MVC新手,遇到了一个问题。我有一个视图,允许用户选择一个项目,然后单击一个按钮来查看该项目的报告。报告也是一个MVC视图,它期望它的模型被初始化。有一个控制器动作方法来初始化模型并调用报表视图。

So my view needs to call the report controller that initialized the model and calls the report view. The call to the report controller has to be made from a JavaScript function.

因此,我的视图需要调用初始化模型并调用报表视图的报表控制器。对报表控制器的调用必须来自一个JavaScript函数。

Finally, I want the report to come up in a new window while leaving the original view up.

最后,我希望报告出现在一个新的窗口中,同时保留原来的视图。

I can call the report View directly using window.open, but that skips the report initializer and the report view crashes when it tries to access the model.

我可以使用窗口直接调用报表视图。打开,但这将跳过报表初始化,当报表视图试图访问模型时就会崩溃。

Is there a way to call a controller using window.open? Can I call the report controller from the report view if the model is null? can I call the report controller from my JavaScript function in the first view?

是否有使用windows .open调用控制器的方法?如果模型为空,我可以从报表视图中调用报表控制器吗?我可以在第一个视图中从JavaScript函数调用报表控制器吗?

Or how do you suggest I handle this? Thanks for your help!

或者你建议我怎么处理这件事?谢谢你的帮助!

URW

URW

Pseudo code follows:

伪代码如下:

Below is the code for the View I am working on. It's a search form. The user can enter some values (or not) and click search, on the top part of the form. the form re-displays to show search results below the search form. below the list of items found, are 2 buttons: One to call the ShowReport function and one to call a Wizard. The 2 buttons are on seperate forms, because both need to submit. At least that's how I see it right now. I can change that, if having 2 forms is a problem.

下面是我正在处理的视图的代码。这是一个搜索表单。用户可以输入一些值(或不输入)并单击表单顶部的search。表单重新显示以显示搜索表单下面的搜索结果。在发现的项目列表下面,有两个按钮:一个用于调用ShowReport函数,另一个用于调用向导。这两个按钮是分开的,因为它们都需要提交。至少我现在是这么看的。如果有两种形式的问题,我可以改变它。

// This is the function that should call the controller to show the report
function ShowReport() 
{

    if (ReportID != null && ReportID > 0) 
    {     
      // I need to call report controller passing ReportID
    }
    else 
    { 
      alert("The Report ID is not valid. Please select a different itemand try again.");
      return; 
    }
}

This function stores the reportID whenever the user selects an item in the list by clicking the radio button at the beginning of the row. It also enables or disables the ShowReport and Run Wizard buttons, depending on the selected item. The report is not available for all items in the list, so this function checks to see if a report is available for the current selection and enables the SHOW Report button if a report is available.

每当用户通过单击行开头的单选按钮选择列表中的项目时,此函数就存储reportID。它还支持或禁用ShowReport并运行向导按钮,具体取决于所选的项目。该报告对列表中的所有项目都不可用,因此该函数检查报告对当前选择是否可用,并在报告可用时启用SHOW report按钮。

function activateStart(annualWaterReportId) {

    // store the ReportID for this ID in a global 
    // in case the user wants to see the Full report
    ReportID = reportId;

    document.getElementById("startButton").disabled = false;
    if (ReportId > 0) {
        document.getElementById("viewReport").disabled = false;
    } else {
        document.getElementById("viewReport").disabled = true;
    }
}

THis function starts the report wizard when the user selects and item and clicks the RunWizard button.

当用户选择并单击RunWizard按钮时,该函数将启动报表向导。

function startAction() {

var elements = document.getElementsByName("Select");
    var id = null;
    for (var i = 0; i < elements.length; i++) {
        if (elements[i].checked) {
            id = elements[i].value;
            break;
        }
    }
    if (id != null) {
        document.getElementById("IDList").value = id;
        document.forms["runWizard"].submit();
    }
    else {
        alert("You must first select an item before pressing the Start Wizard button. " );
    }
}

THe following form displays 3 fields that will become search parameters when the user enters/selects something and clicks Search below the search fields.

下面的表单显示了3个字段,当用户输入/选择某样东西并单击search字段下面的搜索时,这些字段将成为搜索参数。

@using ((Html.BeginForm("Index", "Search", FormMethod.Post, new { onsubmit = "showLoadMask('Searching...')" })))
{
<table class="searchTable">
    <tr>
        <td>
            <div>
                Name:</div>
            <input name="searchName" type="text" value="@ViewBag.searchName" />
        </td>
        <td>
            <div>
                ID Number:</div>
            <input name="searchID" type="text" value="@ViewBag.searchID"/>
        </td>
        <td>
            <div>
                Year:</div>
            <input name="searchYear" type="text" value="@ViewBag.searchYear"/>
        </td>
</tr>
    <tr>
        <td colspan="4">
            <input type="submit" class="smallButton" value="search" />
        </td>
    </tr>
</table>

}

}

next comes the list of items found when the user clicked Search above. Each row is preceded by a radio button, used by the user to select a row before clicking one of the two buttons below the list.

接下来是用户单击上面的搜索时找到的项目列表。每一行前面都有一个单选按钮,用户在单击列表下面两个按钮中的一个之前可以选择一行。

<table style="width: 100%" id="searchResults">
<thead>
    <tr>
        <th>
            Select Person
        </th>
        <th>
            Name
        </th>
        <th>
            City
        </th>
        <th>
            State
        </th>
        <th>
            Zip Code
        </th>
    </tr>
</thead>
<tbody>
@foreach (var searchVM in Model)
        {
            <tr>
                <td>
                    <input type="radio" name="Select" value="@searchVM.Number" onclick="activateStart(@searchVM.YearID) " />
                </td>
                <td>@searchVM.Number
                </td>
                <td>@searchVM.Name
                <td>@searchVM.City
                </td>
                <td>@searchVM.StateID
                </td>
                <td>@searchVM.PostalCode
                </td>
            </tr>
        }
</tbody>

Below the search results are 2 buttons that are critical: One to show the Wizard and one to show the report. This form exists only to allow the user to access a Wizard after selecting an item in the list above.

在搜索结果下面有两个关键的按钮:一个显示向导,一个显示报告。此表单仅允许用户在选择上面列表中的项后访问向导。

<form id="runWizard" method="post" action="@ViewBag.wizardAction">
<input type="button" value="Start Wizard disabled id="startButton" onclick="startAction()" />
<input type="hidden" name="pageAction" id="pageAction" value="NEXT_ACTION" />
<input type="hidden" name="currentPage" value="3" />

I added this form to use for the "View Report" button so I can better control what happens when the button is clicked.

我添加了这个表单用于“视图报告”按钮,以便更好地控制单击按钮时发生的情况。

@using (Html.BeginForm("CallFullReport", "Search", FormMethod.Post, new Dictionary<string, object>{"ReportID", }))
{
// Clicking this button should bring up the report in a new window, while leaving the current window as is.
<input type="submit" value="View Full Report" disabled id="viewReport" onclick="showReport()" />
<input type="hidden" id="ReportID" name="ReportID" value="-1"/>
}

The Controller I want to call is in a seperate dll, The source code is in a file called HomeController.cs the Controller looks like this:

我要调用的控制器是在一个seperate dll中,源代码在一个名为HomeController的文件中。控制器是这样的:

public ActionResult FullReport(int reportID) {
        ReportModel reportModel = null;
        try {
            reportModel = _db.Reports.Find(reportID);
        }
        catch (Exception) {
                // gen up an error message
        }

        return View(reportModel);
    }

Finally, there is the view the controller calls. It displays a report, using the data in reportModel loaded by the controller I've reduced the code to the bare minimum just so I can show you something that makes sense.

最后,还有控制器调用的视图。它显示一个报告,使用控制器加载的reportModel中的数据,我将代码减少到最低限度,这样我就可以向您展示一些有意义的东西。

<table style="width: 100%">
foreach (Var item in ReportModel)
{
 <tr>
     <td class="tableLabel base">Name: </td>
     <td class="tableData base">@Item.Name</td>
 </tr>
 <tr>
     <td class="lineSpacer">&nbsp;</td></tr>
 <tr>
     <td class="tableLabel base">Address: </td>
     <td class="tableData base">@Item.Street1</td>
 </tr>
 @if (Item.Street2 != null && Item.Street2 != "") 
 {
  <tr>
    <td>&nbsp;</td>
    <td>@Item.Street2</td>
  </tr>
  }
  <tr>
     td>&nbsp;</td>
     <td>@Item.City, @Item.StateID @Item.PostalCode</td>
  </tr>
  <tr><td>&nbsp;</td></tr>
  <tr><td class="tableLabel base">Phones:</td><td class="tableData base">@(new HtmlString(phones))</td></tr>
  <tr><td class="tableLabel base">Email:</td><td class="tableData base"><a href="mailto:@Item.Email">@Item.Email</a></td></tr>
}
</table>

That's all the pseudo code I have. I've inherited all this code and I am new to MVC and everything that goes with it. Let me know if I can provide additional info.

这就是我所有的伪代码。我继承了所有这些代码,我是MVC的新成员,所有与之相关的东西。如果我能提供更多的信息,请告诉我。

Thanks bunches

由于束

1 个解决方案

#1


2  

Since there is so much code to post, I'm afraid I can only offer a few generic suggestions. Hopefully they will help solve your problem.

由于要发布的代码太多,恐怕我只能提供一些一般性的建议。希望他们能帮助你解决问题。

First off, any opening of a new window MUST be done client-side. You cannot return a new window from the server. I know you didn't mention this in your use case, but it's important to note.

首先,任何新窗口的打开都必须在客户端完成。不能从服务器返回一个新窗口。我知道您在您的用例中没有提到这一点,但是需要注意这一点。

If you need the model in your report view populated, it may be easiest to call it with Ajax, passing along the data required to populate your view. The following is a jQuery example of this borrowed from Dr. Molle https://*.com/a/3825419/1165998

如果您需要填充报表视图中的模型,那么使用Ajax调用它可能是最简单的,传递填充视图所需的数据。下面是一个jQuery示例,借用了Molle https://*.com/a/3825419/1165998

Give your button that calls the report load a unique id: loadReport

给调用报表加载的按钮一个唯一的id: loadReport

$(document).ready(function () { 
    $('#loadReport').on('click', function (){
        $.post(url, { ReportId: reportId },  function (data) {
            var win=window.open('about:blank');
            with(win.document)
            {
                open();
                write(data);
                close();
            }
        });
    });
});

I think that you can do away with the Html.BeginForm for populating this data, since you want to push it to a new browser window in either case. I would delete the CallFullReport section and just have a single button to load the report (our button with a unique id of loadReport).

我认为你可以去掉Html。BeginForm用于填充此数据,因为无论哪种情况,都希望将其推到新的浏览器窗口。我将删除CallFullReport部分,只有一个按钮来加载报表(我们的按钮具有唯一的loadReport id)。

#1


2  

Since there is so much code to post, I'm afraid I can only offer a few generic suggestions. Hopefully they will help solve your problem.

由于要发布的代码太多,恐怕我只能提供一些一般性的建议。希望他们能帮助你解决问题。

First off, any opening of a new window MUST be done client-side. You cannot return a new window from the server. I know you didn't mention this in your use case, but it's important to note.

首先,任何新窗口的打开都必须在客户端完成。不能从服务器返回一个新窗口。我知道您在您的用例中没有提到这一点,但是需要注意这一点。

If you need the model in your report view populated, it may be easiest to call it with Ajax, passing along the data required to populate your view. The following is a jQuery example of this borrowed from Dr. Molle https://*.com/a/3825419/1165998

如果您需要填充报表视图中的模型,那么使用Ajax调用它可能是最简单的,传递填充视图所需的数据。下面是一个jQuery示例,借用了Molle https://*.com/a/3825419/1165998

Give your button that calls the report load a unique id: loadReport

给调用报表加载的按钮一个唯一的id: loadReport

$(document).ready(function () { 
    $('#loadReport').on('click', function (){
        $.post(url, { ReportId: reportId },  function (data) {
            var win=window.open('about:blank');
            with(win.document)
            {
                open();
                write(data);
                close();
            }
        });
    });
});

I think that you can do away with the Html.BeginForm for populating this data, since you want to push it to a new browser window in either case. I would delete the CallFullReport section and just have a single button to load the report (our button with a unique id of loadReport).

我认为你可以去掉Html。BeginForm用于填充此数据,因为无论哪种情况,都希望将其推到新的浏览器窗口。我将删除CallFullReport部分,只有一个按钮来加载报表(我们的按钮具有唯一的loadReport id)。