I am using MVC3 and I dont want to use Microsoft.Web.Mvc
How do I convert this code to be used in MVC3 ? The view engine is .aspx
Html.Button ("abc", "Button abc", HtmlButtonType.Button)
and also this script
$("button[name=abc]").attr("disabled",true);
Any feedback is appreciated ?
HTML Markup for your button:
<input type="button" name="abc" disabled="true" value="Button abc" />
ASP.NET MVC 3 does not have a built-in HtmlHelper extension method for a button. You could always easily create on:
public static class YourMvcButtonExtensionMethod
{
public static MvcHtmlString Button(this HtmlHelper helper, string text,
IDictionary<string, object> htmlAttributes)
{
// generate the markup for the input/button
}
}
So you really have two options:
use raw HTML markup in your View
create your custom extension method (see above)
"I am using MVC3 and I dont want to use Microsoft.Web.Mvc"
That just sounds confusing...
Anyway you can use the button element instead.
<button disabled='true'>Button abc</button>
Related
I have a View MyView.cshtml with the following content:
#using MyProject.ViewModels
#model MyProject.ViewModels.MyViewViewModel
<form asp-action="Test" method="Post">
<component type="typeof(MyProject.Views.Home.Test)" render-mode="ServerPrerendered" />
<input type="submit" value="send"/>
</form>
And I have the Razor Component Test.razor with the following content (with Blazor Syntax):
#page "/Test"
<div class="form-group top-buffer #Visible">
<div class="row">
<div class="col-2">
<label asp-for="TestName" class="control-label"></label>
</div>
<div class="col-3">
<input asp-for="TestName" class="form-control" />
<span asp-validation-for="TestName" class="text-danger"></span>
</div>
</div>
</div>
<button #onclick="Show">Show</button>
#code {
public string Visible { get; set; } = "hidden";
protected async Task Show()
{
Visible = "";
}
}
The Class MyViewViewModel would look like this:
namespace MyProject.ViewModels
{
public class MyViewViewModel
{
[Display(Name = "Test Name:")]
public string TestName { get; set; }
}
}
Works all pretty fine so far. However I now want to use this component as part of a Web form which will be sent to the controller after submission. That's why I need to access and change properties of my ViewModel 'MyViewViewModel'. Unfortunately I did not find any answer in the internet on how to do that. I can't use #model MyProject.ViewModels.MyViewViewModel like in the view because this will give me a compilation error. I wonder if I need to use #inject, but if yes, I don't know how...
(parts are used from this example: https://jonhilton.net/use-blazor-in-existing-app/)
When you mix Blazor in a Razor Page, you can do the following:
Render a Razor Component
Interact with a Razor Component
Pass a Razor Component values
Please keep in mind that you are dealing with two different life-cycles. So if you do work inside of a Razor Component, the component will update but not effect the Razor Page it is hosted inside of. So mixing Razor Components and Pages with forms would be difficult.
More specifically to the OP. To pass data from your ViewModel to the component you may use the following method.
#using MyProject.ViewModels
#model MyProject.ViewModels.MyViewViewModel
<form asp-action="Test" method="Post">
<component type="typeof(MyProject.Views.Home.Test)"
render-mode="ServerPrerendered"
param-Name="#Model.TestName"/>
<input type="submit" value="send"/>
</form>
Test.razor
<h3>HelloWorld</h3>
Hello #Name
#code {
[Parameter]
public string Name { get; set; } = "undefined";
}
About life cycles
Basically when you have a button in Blazor, it will trigger an event which causes the component to re-render. You could imagine it like an iframe, or update-panel. When you have a button in a Razor page, it does a HTTP call round trip and reloads the page entirely. There is no event system in place to tell Blazor to invoke an HTTP call round trip to refresh the Razor page's content and vise versa. You can only one-way data-bind from Razor pages to Blazor, think write-only, and only when the page loads.
To hopefully add to the info. With a ASP.Net Core MVC project host Blazor webassembly, I was trying to pass a viewmodel into a razor component using this code in my view cshtml file:
<component Type="typeof(Leave)" render-mode="WebAssembly" model="new { model = (MyViewModel)#Model})"/>
But it would fail to render the razor component if I tried to access data in the viewmodel from the razor component with an Object not set exception. I think it was accessing the data before the view model has been initialized. Maybe if I set a default value this could avoided?
I found by using this instead I was able to get it working.
#(await Html.RenderComponentAsync<Leave>(RenderMode.WebAssembly,new { model = (MyViewModel)#Model}))
Edit
Seems you also need to register the viewModel class in the services in the Blazor WASM project in the Program.cs file.
builder.Services.AddScoped(sp => new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddScoped<MyViewModel,MyViewModel>(); // <= add this line
await builder.Build().RunAsync();`
Without that I would get an error saying the property could not be found.
Hopefully this saves someone else some time :-)
I created an extension method based on this answer to the SO question c# - How can I create a Html Helper like Html.BeginForm - Stack Overflow and it works fine.
Can I move the embedded HTML in the extension method into a partial view and use that partial view in the method while preserving it's current behavior? In particular, I want to be able to 'wrap' a block of arbitrary HTML.
I ask not out of any pressing need, but simply out of a desire to maintain HTML consistently, e.g. as views and partial views. I imagine it will be a lot easier to spot any problems with the HTML if it's in a view or partial view too.
Here's the HtmlHelper extension method:
public static IDisposable HelpTextMessage(this HtmlHelper helper, bool isHidden, string heading)
{
TextWriter writer = helper.ViewContext.Writer;
writer.WriteLine(
String.Format(
"<div class=\"help-text {0}\">",
isHidden ? "help-text-hidden" : ""));
writer.WriteLine(
String.Format(
"<div class=\"help-text-heading\">{0}</div>",
heading));
writer.Write("<div class=\"help-text-body\">");
return new HelpTextMessageContainer(writer);
}
Here's the HelpTextMessageContainer class:
private class HelpTextMessageContainer : IDisposable
{
private readonly TextWriter _writer;
public HelpTextMessageContainer(TextWriter writer)
{
_writer = writer;
}
public void Dispose()
{
_writer.Write("</div></div>");
}
}
In a view, I can use the extension method like this:
#using(Html.HelpTextMessage(Model.HelpText.IsHelpTextHidden(Model.SomeHelpMessage), "Something"))
{
#:To do something, first do something-more-specific, then do another-something-more-specific.
}
Or I could use it like this too:
#using(Html.HelpTextMessage(Model.HelpText.IsHelpTextHidden(Model.SomeHelpMessage), "Something"))
{
<p>To do something, first do something-more-specific, then do another-something-more-specific.</p>
<p>Also, keep in mind that you might need to do something-else-entirely if blah-blah-blah.</p>
}
I haven't found any way to move the "embedded HTML" into a partial view exactly, but a slightly more-friendly way to encapsulate the HTML in a way that provides HTML and Razor syntax highlighting and Intellisense is to move into a view helper function in a file under the app App_Code folder as described in this post on "Hugo Bonacci's Blog".
Here's my helper function:
#helper HelpTextMessage(bool isHidden, string heading, Func<object, object> content)
{
<div class="help-text #(isHidden ? "help-text-hidden" : "")">
<div class="help-text-heading">
#heading
</div>
<div class="help-text-body">
#content(null)
</div>
</div>
}
Assuming the above helper function is in a file named ViewHelpers.cshtml in the App_Code folder, it can be called in a view like this:
#ViewHelpers.HelpTextMessage(false, "Something",
#:To do something, first do something-more-specific, then do another-something-more-specific.
)
or this:
#ViewHelpers.HelpTextMessage(false, "Something",
<p>To do something, first do something-more-specific, then do another-something-more-specific.</p>
<p>Also, keep in mind that you might need to do something-else-entirely if blah-blah-blah.</p>
)
I like having the embedded HTML in a view more than I do being able to use the #using(Html.HelpTextMessage(...){ ... } syntax, so I'm pretty happy with this as a solution.
I'm using editor from Kendo UI, so I have big problem.
I don't know how display items which are returned by editor.
Editor convert something like:
<img src="someurl" />
to:
lt;p><img src="someurl"/></p>
and I keep converted string in database, and try display it with:
#Html.Raw(item.description)
where description is string returned by kendo.
So I have no idea how display it correctly in my View
Any help would be appreciated.
There is an option of the KendeUI editor called encoded which configures whether the Editor should submit encoded HTML tags or not.
The default value for encoded is true
If you wan't to store the unencoded text use this sniplet when creating your editor:
$("#Editor").kendoEditor({
encoded: false
});
But because you are not sending encoded text to the server the Asp.net request validator kicks in and it will abort your request.
If you are using strongly typed views what you can do is to use the AllowHtmlAttribute on your model property:
View:
#model MyModel
#using(Html.BeginForm("SomeAction", "SomeController"))
{
#Html.TextAreaFor(m => m.Editor)
<input type="submit" value="Save" />
}
<script type="text/javascript">
$(function(){
$("#Editor").kendoEditor({
encoded: false
});
});
</script>
Model:
public class MyModel
{
[AllowHtml]
public string Editor { get; set; }
}
Controller action
public ActionResult SomeAction(MyModel myModel)
{
//Save to db, etc.
}
You also need to set the following in your web.config or this attribute won't have effect in .NET 4.0:
<httpRuntime requestValidationMode="2.0"/>
I found this solution for MVC:
in View
<div class="editor-field">
#(Html.Kendo().EditorFor(model => model.HtmlField).Encode(false))
#Html.ValidationMessageFor(model => model.HtmlField)
</div>
in model:
[DataType(DataType.Html)]
[AllowHtml]
public string HtmlField{ get; set; }
That was enough
Simplier way to do it is make changes in controller, no in view and model. So:
View
$("#Editor").kendoEditor();
Model
public class MyModel
{
public string Editor { get; set; }
}
Controller
Editor = Server.HtmlDecode(Editor);
HtmlDecode
The editor templates generated from the .NET Wrappers aren't working any more. Here is a fix.
http://pknopf.com/blog/kendo-ui-editor-templates-for-asp-net
I'm not even sure if this is possible, but I thought I would check to see if there is any way to make this easier.
First, I have some repeated markup in my site that looks like this:
<div class="module">
<h3>Title</h3>
<div>
<p>Information goes here</p>
</div>
</div>
What I want to do is wrap this up in some kind of helper/section so that I could do something like this
#MyHelper("This is my Title") {
<p>Here is my custom markup</p>
}
Then, when it renders, it would inject the title passed in through the parameter between the <h3></h3> and the custom markup in the divs. The custom markup could be anything from test, to form controls, to a partial view. Is this something that is possible?
There's also the other way, without disposable trick, which also requires a little less work, great for little helpers.
#helper MyHelper(string title, Func<object, object> markup) {
<div class="module">
<h3>Title</h3>
<div>
<p>#markup.DynamicInvoke(this.ViewContext)</p>
</div>
</div>
}
Usage of this helper looks like this:
#MyHelper("This is my Title",
#<p>Here is my custom markup</p>
)
Or with multiple lines:
#MyHelper("This is my Title",
#<text>
<p>More than one line</p>
<p>Of markup</p>
</text>
)
Telerik MVC controls used this trick for example to let you add your javascript code at the document load.
Here's also a nice example. There's also some information here.
Well, here's a "standard" way of doing something close to it, using an HTML helper extension. A very simple version of what Html.BeginForm() does.
Approach: Simply return an IDisposable, and let the using statement take care of the rest.
This is just an example of the concept (although it works). Not intended for immediate reuse. Written quickly with lots of shortcuts, not production code, plenty of opportunities for improvement and optimization, may have silly mistakes, could use TagBuilder etc. etc. Could easily be modified to reuse the Wrapper class for different... wrappings (there may even be a generic one already in ASP.NET MVC - haven't had a need for one).
public static class WrapHelper
{
private class Wrapper : IDisposable
{
private bool disposed;
private readonly TextWriter writer;
public Wrapper(HtmlHelper html)
{
this.writer = html.ViewContext.Writer;
}
public void Dispose()
{
if (disposed) return;
disposed = true;
writer.WriteLine(" </div>");
writer.WriteLine("</div>");
}
}
public static IDisposable Wrap(this HtmlHelper html, string title)
{
TextWriter writer = html.ViewContext.Writer;
writer.WriteLine("<div class=\"module\">");
writer.WriteLine(" <h3>" + html.Encode(title) + "</h3>");
writer.WriteLine(" <div>");
return new Wrapper(html);
}
}
Usage:
#using (Html.Wrap("Title"))
{
<p>My very own markup.</p>
}
#TheKaneda, Thanks for the insight. I took your idea and extended it, such that you supply a PartialView name and it knows how to parse it.
<Extension()> _
Public Function UseTemplate(ByVal html As HtmlHelper, ByVal PartialView As String) As IDisposable
Return New TemplateWrapper(html, PartialView)
End Function
Public Class TemplateWrapper
Implements IDisposable
Private _HtmlHelper As HtmlHelper
'Index 0 is header
'Index 1 is footer
Private _TemplateWrapper As String()
Public Sub New(ByVal Html As HtmlHelper, ByVal PartialView As String)
_TemplateWrapper = Html.Partial(PartialView).ToHtmlString.Split("##RenderBody()")
_HtmlHelper = Html
_HtmlHelper.ViewContext.Writer.Write(_TemplateWrapper(0))
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
_HtmlHelper.ViewContext.Writer.Write(_TemplateWrapper(1).Substring(12))
End Sub
End Class
Use the same usage as #TheKaneda's example. In your partial view, instead of calling #RenderBody(), just put ##RenderBody() which acts as a flag for the middle part of your content. Sorry for the VB translation.
Uses an example of my usage.
Using Html.UseTemplate("ContentWrapper")
#Html.EditorFor(Function(m) m.Var1, "TemplateHint")
#Html.EditorFor(Function(m) m.Var2, "TemplateHint")
#Html.EditorFor(Function(m) m.Var3)
End Using
My Partial looks like this...
<div class="content">
##RenderBody()
</div>
If you are using Razor and MVC 3 it's real easy to write a quick helper method that would go inside the app_code folder, (I'll name it MyHtmlHelpers)
I'd try something a little different and a little easier such as:
#helper myTemplate(string title, string markup){
<div class="module">
<h3>#title</h3>
#markup
</div>
}
And the way you use it from a .cshtml file is as followed:
#MyHtmlHelpers.myTemplate('title','markup')
It should work, if I understand you correctly.
This is going to seem like a bit of a silly endeavor, but it's something I want to learn nonetheless.
Right now, in ASP.NET MVC 3.0, you need to use the syntax #using (Html.BeginForm()) { and then later, the } to close a form block to get the fancy new 'unobtrusive javascript', lest you want to write all of it by hand (which is fine).
For some reason (Read: *OCD*) I don't like that. I'd really rather do this..
#Html.BeginForm()
<div class="happy-css">
</div>
#Html.EndForm()
Seem stupid yet? Yeah, well to each their own. I want to understand why it is working how it is and mold it to my liking. So I thought the first place I would start digging is the MVC 3.0 source itself. So I jumped into codeplex to find the BeginForm Extension method.
( http://aspnet.codeplex.com/SourceControl/changeset/view/63452#288009 )
So now I am a little confused as to how to begin achieving my goal. Reading through the code, I discovered that they all go down to a root method (not surprising, as most extension methods seem to be hierarchical methods all reaching down into a single one to avoid redundancy).
private static MvcForm FormHelper(this HtmlHelper htmlHelper, string formAction, FormMethod method, IDictionary<string, object> htmlAttributes) {
TagBuilder tagBuilder = new TagBuilder("form");
tagBuilder.MergeAttributes(htmlAttributes);
// action is implicitly generated, so htmlAttributes take precedence.
tagBuilder.MergeAttribute("action", formAction);
// method is an explicit parameter, so it takes precedence over the htmlAttributes.
tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(method), true);
HttpResponseBase httpResponse = htmlHelper.ViewContext.HttpContext.Response;
httpResponse.Write(tagBuilder.ToString(TagRenderMode.StartTag));
return new MvcForm(htmlHelper.ViewContext.HttpContext.Response);
}
What I am not seeing here is how this method relates to the unobtrusive javascript. If I simply type out ..
<form action="/Controller/Action" method="post">
and then put in my validation like so...
#Html.ValidationSummary(false)
I do not get the unobtrusive javascript. But if I use
#using (Html.BeginForm()) { then I do. I've even examined the generated markup and I really can't find the difference.
Now then it gets strange. If I just type in ...
#Html.BeginForm() and then put all of my form code, the form works and I get the unobtrusive javascript, but I have to manually type in </form> at the end. #Html.EndForm() doesn't work. But ontop of that, I now get the text System.Web.Mvc.Html.MvcForm written to the output stream right beneath the <form action="/Controller/Action" method="post"> html.
Can someone enlighten and/or help me?
The answer to your underlying question (i.e. how to use BeginForm/EndForm syntax) is to do it in the following manner:
#{ Html.BeginForm(...); }
<div> content</div>
#{ Html.EndForm(); }
Unfortunately the Razor syntax right now is a bit more verbose when invoking helpers that write to the output (as opposed to the majority of helpers which just return an html snippet). You could probably make this easier by writing your own extension methods like so:
public static IHtmlString FormBegin(this HtmlHelper helper, ...) {
helper.BeginForm(...);
return new HtmlString("");
}
public static IHtmlString FormEnd(this HtmlHelper helper) {
helper.EndForm();
return new HtmlString("");
}
The reason it works I believe is that the BeginForm method returns an MvcForm object and not html, it writes the html directly to the page. When the using block ends it is disposed and it writes the closing end tag. That's the reason you see the text System.Web.Mvc.Html.MvcForm appear in your output. You have to put the closing tag in there manually because the MvcForm object isn't disposed.
The using syntax is like doing this:
#{ MvcForm mf = Html.BeginForm(); /* writes directly to html stream */ }
<div class="happy-css">
</div>
#{ mf.Dispose(); /* like calling mf.EndForm() */ }