Note: I'm a front-end developer wearing a .Net developer's hat for now. Laughable, I know, but how I ended up in this mess is not the point of this question. With that disclaimer out of the way, here's what is happening.
As the title suggests, I need to pass a quite long HTML string (as in multiple pages of text) from a View to a Controller. I spent the last few days researching various ways to achieve this. TBH, some things made sense while some didn't.
Here's my code piece inside View:
var html =
"<form id='htmlContent' action='" + customUrl + "' method='post'>" +
"<input type='hidden' name='content' id='contentStr'>" +
"</form>";
// string literal html gets appended to some element...
$("#htmlContent").submit();
A few things I'd like to point out here:
- I'm using a string literal to construct the form here because this DOM needs to be dynamically attached to other element at some point.
- Whether I'm using a valid HTML string is out of the question. I've already tested its validity separately and everything looks fine.
- I'm intentionally using jQuery's
submit()
method instead of using Ajax
call.
Controller:
[HttpPost]
public ActionResult ParseHtml(FormCollection form)
{
string htmlStr = form["content"].ToString();
....
// some code in between, but the first line appears to be causing an error or
// the value is not being retrieved.
....
return new EmptyResult();
}
I understand I'm working within the context of MVC framework and I sort of comprehend the concept of it. But, knowing how to implement it with my very limited knowledge is another thing (especially when you inherited a bad code base from someone who's long gone from your project!)
I'd like to think this is quite straightforward and easy to do, but I've been spinning my wheels for much longer than I'd like to. Any pointers to the right direction will be much appreciated.
In this minimal reproducible answer, I'll show you how to get this working, and you can run with it from here:
Index.cshtml
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var url = '@Url.Action("Create","Stack")';
var html = $("<form id='htmlContent' action='"+url+"' method='post'><input type='hidden' name='content' id='contentStr' value='oranges'/></form>");
$(body).append(html);
$("#htmlContent").submit();
});
</script>
@{
ViewBag.Title = "title";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>title</h2>
Controller.cs
using System.Web.Mvc;
namespace MvcPlayground.Controllers
{
public class StackController : Controller
{
//
// GET: /Stack/
public ActionResult Index()
{
return View();
}
public ActionResult Create(FormCollection form)
{
string htmlStr = form["content"].ToString();
return View("Index");
}
}
}
If you place a breakpoint on the return View("Index");
, you'll see htmlStr is "oranges", which is the value of the appended textbox.
Not answering the main part of your question as I'm not certain of all of the details, sorry. I'm not saying you're doing it "wrong" by any stretch as I'm not certain what peripherally may make it seem like it is necessary, but you may be creating a situation where you're going to have a major headache on the backend parsing and what not. Good chance that a lot of this is all wrong as I'm not certain of the requirements so I apologize.
"I'm using a string literal to construct the form here because this
DOM needs to be dynamically attached to other element at some point."
You're wanting to re-render that same element in another component? That sounds like you're looking for a partial view. With that, you can render it in View1 and use it in View2 with the same data. If you're trying to create elements on the fly, I imagine you're using some type of pattern (ie there's a project I'm working on where I iterate over a collection and do
<input type='text' id='attribute_@(item.Id)' name='attribute_@(item.Id)' />
And then iterate over the FormCollections AllKeys element to get them (parsing out the attribute_ and what have you like:
foreach(var key in form.AllKeys)
{
var id = Convert.ToInt32(key.Replace("attribute_", "")); // may want to TryParse
var item = Item.GetItemById(id);
item.Value = form[key];
item.Update();
}
Somewhere in the view, you're using javascript to set document.getElementById("contentStr") (not sure if intentional, but your id and name are different. Not a bad thing per se, but could lead to an oops)? Then again, not sure what var html = is being used for here. Razor views you could just do the regular html of [form] ... [/form]. Are you doing something like this prior to the submit action?
$('#content').val(html);