I have a simple MVC application that retrieves DB Server, database, username and password from the user to store in an XML file. I want to add a "Test Connection" button to the screen and have it execute a method on the controller called TestConnection. The problem is the TestConnection method resets all the information on the screen when clicked since the View is being returned with no model. (because a GET operation is occurring). Here is my code:
From the Controller (named FrameworkConfigurationController.cs)
public ActionResult TestConnection()
{
return View("Index");
}
[HttpPost]
public ActionResult TestConnection(FrameworkConfigurationViewModel viewModel)
{
// TODO: Test will occur here
viewModel.DbConnectionMessage = string.IsNullOrEmpty(viewModel.DatabaseName) ? "Connection unsuccessful" : "Connection successful";
return View("Index", viewModel);
}
From my View (FrameworkConfiguration/Index):
#model Framework.ViewModels.FrameworkConfigurationViewModel
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>FrameworkConfigurationViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ServerName)
</div>
#* Edited for brevity *#
<button type="submit" onclick="location.href='#Url.Action("TestConnection")'">
Test Connection</button>
#Html.ValueFor(model => model.DbConnectionMessage)
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to Dashboard", "Index", "Home")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Admittedly, I am new to MVC programming. I'm coming from a Silverlight/MVVM background so the concept is not foreign to me...the disconnected nature of web programming is. I've followed some tutorials out there, but none of them seem to cover this type of thing - every example is contrived. I know how to do this with webforms and code-behind, but I would like to accomplish this with MVC.
Is there some way to "force" the POST operation instead of GET? I was under the impression that
<button type="submit">
accomplished that. Perhaps the implementation of the onclick I have written isn't correct. I am sure this is HTML 101 stuff, but I can't seem to find a simple answer to this.
Thanks for any help you can offer,
Jason
Why not have the Test Connection button trigger an Ajax action to call the controller, and display the result?
That way you avoid submitting your entire page.
In case you're not familiar with the details, here's a good overview on getting started with Ajax and MVC 4
http://ofps.oreilly.com/titles/9781449320317/ch_AJAX.html
Related
.NET Core v6
MVC Web App with Entity Framework Core
I scaffolded a database table and it created a "db context", then I scaffolded default Controller and Views.
On the home page, I want to create a search box where you put in the primary key, or id. On submit, I want the value passed to the default Edit controller. Essentially, I want someone to be able to pull up a single record to Edit, if they know the primary key (id).
Here is what I have for a search box
<form asp-controller="MyTables" asp-action="Edit">
<p>
PIN: <input type="text" name="id" />
<input type="submit" value="Find" />
</p>
</form>
Here is the default Edit method inside the Controller.
// GET: MyTables/Edit/XYZ
public async Task<IActionResult> Edit(string id)
{
if (id == null)
{
return NotFound();
}
var MyTable = await _context.MyTables.FindAsync(id);
if (MyTable == null)
{
return NotFound();
}
return View(MyTable);
}
When I run this, it doesn't work, but I don't know how to set it up. How can I make this work? The only way I've been able to pull a record is by adding method="get" to the form, but then it creates a URL structure using "id" as a parameter like this localhost/MyController/Edit?id=XYZ. This structure won't work because I'm unable to save the record when I've navigated to the page in this way.
I appreciate any pointers or ideas.
Thank you
EDIT AFTER COMMENTS:
It has been suggested that I could go ahead and use the method="get", thereby selecting the correct record. The URL would be in this format: localhost/MyController/Edit?id=XYZ. A proposed solution is to fix my POST action to be able to save the record when using such URL paths. I'm not sure why, but it will only save right now if the URL path is in this format: localhost/MyController/Edit/XYZ (no parameter ?id =).
Here is a version of my default POST Edit action in the controller.
// POST: MyTables/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(string id, [Bind("...,...,...,...,...,...,PrimaryKeyField")] MyTable myTable)
{
if (id != myTable.PrimaryKeyField)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(myTable);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MyTableExists(myTable.primaryKeyField))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(MyTable);
}
In the Edit view, to initiate the POST action, here's some of the Edit Form markup:
#model myApp.Models.MyTable
...
<form asp-action="Edit">
...
<div class="form-group">
<label asp-for="PrimaryKeyField" class="control-label"></label>
<input asp-for="PrimaryKeyField" class="form-control" />
<span asp-validation-for="PrimaryKeyField" class="text-danger"></span>
</div>
...
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
The reason I'm saying it won't Save is when I click Submit on the Edit form, it brings up this HTTP error:
This localhost page can’t be found. No webpage was found for the web address: https://localhost:7020/MyTables/Edit
HTTP ERROR 404
In the Edit View, I added a reference to the Model.
#model myApp.Models.MyTable
In the form, I added a Tag Helper.
<form asp-action="Edit" asp-route-id=#Model.PrimaryKeyField>
This is working.
I noticed in the URL pattern of /Edit/XYZ, the form's asp-action uses this pattern. I noticed with the URL pattern of /Edit/?id=XYZ, the form's action uses /Edit with NO ID. Therefore, I figured out a way to add the id to the form's action by using the asp-route-id tag helper. The form submits the data properly now.
I'm trying to submit a simple form for my ASP.NET MVC website, but I keep getting a StackOverFlow Exception. I don't understand what I'm doing wrong; it should be a pretty straightforward process...
Here is the form code:
<form action="/Home/SubmitAnnouncements" method="post">
<textarea name="announcementcode" style="width:100%; height:800px">#Model.RawAnnouncementCode</textarea>
<div id="find_account" class="two columns"><input id="find_account_btn" class="link_button" type="submit" name="Submit" value="Submit New Announcements" /></div>
</form>
And here is the Controller code for the action:
[HttpPost, ValidateInput(false)]
public ActionResult SubmitAnnouncements(string announcementcode)
{
SubmitAnnouncements(announcementcode);
return RedirectToAction("Index", "Home");
}
This problem stated when I added [HttpPst, ValidateInput(false)], but I need to do that, because the user is submitting raw HTML code. Any ideas anyone?
The ValidateInput attribute didn't cause your error, you just never reached the point in your code that causes the StackOverflowException until it was added.
If you look at the first line of your action, you'll notice you're calling the same method.
In a ASP.NET MVC website; does every view need to have a corresponding/associated Model and Controller?
I am building the bare bones of my website; so I have created all the views but not the Models or Controllers yet. I want to be able to view a page (that contains no content associated with a model or any functionality that a controller should handle - yet). So at this point every view (cshtml page) is a static HTML page.
But when I go to access any view/page I get the error:
The resource cannot be found. Description: HTTP 404. The resource you
are looking for (or one of its dependencies) could have been removed,
had its name changed, or is temporarily unavailable. Please review
the following URL and make sure that it is spelled correctly.
Requested URL: /TeamMember/raiseIssue
raiseIssue.cshtml content:
#{
Layout = "layouts/main.cshtml";
}
<form action="#ViewBag.PostUrl" method="post">
<div class="row feedback-input text-center">
<textarea name="Text"></textarea>
</div>
<div class="row text-center">
<button type="submit" class="btn btn-default btn-standard">Submit</button>
</div>
</form>
MVC do not allows to browse the view directly. What you can do is create empty controller method like below
public ActionResult RaiseIssue()
{
return View();
}
in controller TeamMemberController
One other thing, please make sure that proper route are configured in RouteConfig.cs
I hope using this method you will be able to browser the view with writing much code in controller or model/
I'm following the video on Microsoft's Virtual Academy named "Developing ASP.NET MVC 4 Web Applications Jump Start". In part 5: Integrating Javascript and MVC 4 they start showing off how to use PartialViewResults. I've copied the code exactly as they have in the video, however, I'm getting a different result. They don't show some of the code (SessionController) and it was required for me to figure that part out myself, so maybe that's where I'm messing up.
The problem is that my partial view being called by Html.Action is showing up as plain text instead of the HTML. Like below
I've tried Html.Action, Html.RenderAction, Html.Partial and Html.RenderPartial and all seem to give the same results. Any clue what I might be doing wrong here? I don't want to flood this post with a massive list of code, so I'll post code as requested, if necessary.
EDIT: Requested Razor Code*
Step1:
#model MVC_Tutorial2.Models.Session
<h3>
#Model.Title
</h3>
<div>
#Model.Abstract
</div>
#Html.Action("_GetForSession", "Comment", new { sessionID = Model.SessionID })
Step2:
#model IEnumerable<MVC_Tutorial2.Models.Comment>
<div id="comments>
<ul>
#foreach (var comment in Model) {
<li>#comment.Content</li>
}
</ul>
#using (Ajax.BeginForm("_Submit", "Comment", new AjaxOptions() { UpdateTargetId = "comments" })) {
#Html.AntiForgeryToken()
#Html.Action("_CommentForm", new { SessionID = ViewBag.SessionID })
}
</div>
Step3:
#model MVC_Tutorial2.Models.Comment
#Html.HiddenFor(m => m.SessionID)
<div>
#Html.LabelFor(m => m.Content)
#Html.EditorFor(m => m.Content)
</div>
<button type="submit">Submit Comment</button>
You'll get this exact behaviour if you haven't correctly linked in the required scripts. Try adding the following at the top of your main view (not the partial):
<script src="~/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
Obviously make sure to include the correct version of jQuery you have available in your project.
Update
As you already have the scripts there, something else is obviously wrong. First thing I notice is this:
<div id="comments>
Note the missing quotation-mark. As you have UpdateTargetId = "comments", this may be the cause of your problem.
I have never done a POST request via Razor and MVC4. I think i have the core methods and stuff down but i am having difficulty fulfilling an actual POST request.
Here is the Razor View page code...
#model UserJob
#Html.HiddenFor(Model => Model.UserCode)
#Html.DropDownList("jobCode")
<input type="submit" value="Add" class="btn btn-default" />
And the method which i want to fulfil the POST method is.....
[HttpPost]
public ActionResult AddSkill(UserJob model)
{
db.UserJobs.Add(model);
db.SaveChanges();
return RedirectToAction("Jobs", new { UserCode = model.UserCode });
}
You Razor view needs to have the form. Either use #Html.BeginForm(...) to enclose your inputs, or just write HTML form markup yourself.