ASP.NET MVC with Spring.NET and ModelBinder - asp.net-mvc

I'm working on a demo that makes use of Spring.NET IoC capability in ASP.NET MVC . It's kind of like the MyBlog application presented on pair programming video tutorial on www.asp.net site. I've completed the same demo using Microsoft's Unity framework and now want to try out the Spring container.
To that end I've implemented a simple IControllerFactory that first creates the Spring object factory like that:
IObjectFactory factory;
(....)
factory = new XmlObjectFactory(new FileSystemResource(application.Server.MapPath("objects.xml")))
and next it gets the controller from that factory like that:
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
IController result = context.GetObject(controllerName) as IController;
return result;
}
(error handling stripped for simplification purposes).
Now somewhere in my HomeController I have this kind of action:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddEntry([Bind] BlogEntry entry, int id) {
entry.EntryDate = DateTime.Now;
....
And here's the part of AddEntry.aspx view that defines the editors for entry parameter (really basic stuff):
<form method="post" action="/Home/AddEntry/<%= ViewData["id"] %>">
<table>
<tr>
<td><label for="Title">Title</label></td>
<td><input name="entry.Title" type="text"/></td>
</tr>
<tr>
<td><label for="Text">Content</label></td>
<td><input name="entry.Text" type="text"/></td>
</tr>
</table>
<br />
<input type="submit" value="Add entry" />
<input type="button" value="Cancel" onclick="history.back(-1);" />
</form>
Now here's the deal:
When I'm using the Unity IoC it works like a charm. "entry" parameter gets deserialized from my form like it should and the line
entry.EntryDate = DateTime.Now;
completes without problems.
However when I switch to Spring.NET object factory (like described above) things begin to go nuts. First of all the parameter "entry" turns null so an exception is thrown.
To track the possible problem on my end I've implemented a sort of custom IModelBinder that looks like that:
public class BlogEntryBinder : IModelBinder {
public ModelBinderResult BindModel(ModelBindingContext bindingContext) {
ModelBinderResult result = ModelBinders.DefaultBinder.BindModel(bindingContext);
return result;
}
}
When I come here using the Unity framework and drill down from bindingContext to HttpRequest I see that the Request.HttpMethod is "POST" and Request.Form is properly filled. When I do the same using Spring.NET the method is "GET" and Request.Form is empty.
When however I step to my controller action (AddEntry) and drill down to the Request in both situations I see that the Request.HttpMethod and Request.Form have their proper values.
Now the question is how do I fix the version with Spring.NET so that it works just like the one that uses Unity framework?

I've found the answer!
My object definition looked like that:
<!-- Controlers -->
<object name="Home" type="MyBlog.Controllers.HomeController">
<property name="BlogService" ref="BlogService" />
<property name="BlogEntryService" ref="BlogEntryService" />
<property name="BlogEntryCommentService" ref="BlogEntryCommentService" />
</object>
Nevermind the properties being set what it actually does is it returns the same instance every time I ask for this object using
IController result = context.GetObject(controllerName) as IController;
So when I've changed the definition to
<!-- Controlers -->
<object name="Home" type="MyBlog.Controllers.HomeController" singleton="false">
<property name="BlogService" ref="BlogService" />
<property name="BlogEntryService" ref="BlogEntryService" />
<property name="BlogEntryCommentService" ref="BlogEntryCommentService" />
</object>
everything started work just fine.
Best regards,
Matthias.

just an additional note for clarifying this behavior: Controllers are treated as prototypes by the ASP.NET MVC framework, but Spring defaults to singleton mode. Therefore you need to explicitly mark your object as non-singleton in the container configuration. The upcoming Spring MVC integration module will take care of this, so you won't run into this then.
hth,
Erich

Related

Futures : Taghelpers --> Razor Components

I'm wondering if anybody has any views or knowledge on where the future of TagHelpers & Razor Components lay. My question is only with regard to initial rendering. Not using C# code on the client-side.
I love the razor component model of working in the sense that the basic component is laid out in markup, then there is code behind.
This being compared to TagHelpers generating the markup.
Take this TagHelper label component I use for example...
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace gMIS.TagHelpers
{
[HtmlTargetElement("glabel", TagStructure = TagStructure.WithoutEndTag)]
public class glabelTagHelper : TagHelper
{
#region Attributes
[HtmlAttributeName("id")]
public string id { get; set; }
[HtmlAttributeName("class")]
public string cls { get; set; }
[HtmlAttributeName("xy")]
public string xy { get; set; }
[HtmlAttributeName("style")]
public string style { get; set; }
[HtmlAttributeName("value")]
public string value { get; set; }
#endregion Attributes
public override void Process(TagHelperContext context, TagHelperOutput output)
{
//START with the container DIV
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
if (id != null) output.Attributes.Add("id", id);
if ((xy != null) && (xy != null)) output.Attributes.Add("class", "xy" + xy);
if (style != null) output.Attributes.Add("style", "display:inline-block; font-weight:bold;" + style); //*** Any subsequent WIDTH passed in with supercede the default provided here!
else output.Attributes.Add("style", "display:inline-block; font-weight:bold;");
if (cls != null) output.Attributes.Add("class", cls);
//Insert data value
if (value != null) output.Content.AppendHtml(value);
}
}
}
I would love it if this could be coded something like...
<div id="{inject id}" class="{inject class}" style="{inject style}">{inject text}</div>
...rather than using C# to create the basic markup.
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
Then the code behind interacts (only server-side) to finish the configuration of the basic component markup. That way, you can see the basic markup rather than the more difficult to read and visualize C# construction of the markup.
With a basic label this seems like not much of a gain, but with more complex components, being able to visualize the markup would be a real boon.
<div class="{inject class}" id="{inject id}" style="{inject style}">
<input name="{inject name}" id="{inject id}" style="{inject style}" type="text" value="-4" data-val-required="&nbsp;Req!" data-val="true">
<input id="{inject id}" style="{inject style}" type="text" placeholder="Start typing here to search..." autocomplete="off">
<select id="{inject id}" style="{inject style}" size="1">
</select>
<script type="text/javascript">
$(document).ready(function () { $('#ext_IT_Task_Reported_By_ID').glookupInit('/TagHelpers/InternalContactLookup'); });</script>
<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="{inject id}"></span>
</div>
Does anybody know where Taghelpers is heading the longer term? Towards the Razor Component way of construction perhaps. Apologies if my post isn't clear enough. I have thought hard about how to communicate my question. I do hope it's not confusing.
Not sure exactly what you're asking here, but I think you're not understanding how tag helpers work. You don't have to add each attribute manually to the output and you certainly don't need backing properties if you don't actually need the value for the purposes of the tag helper. Razor leaves any additional attributes unmolested.
[HtmlTargetElement("glabel")]
public class glabelTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.TagMode = TagMode.StartTagAndEndTag;
var style = "display:inline-block; font-weight:bold";
if (output.Attributes.TryGetAttribute("style", out var attr))
{
style += $";{attr.Value}";
}
output.Attributes.SetAttribute("style", style);
}
}
Based on your code, the only thing you're modifying is the style attribute, so everything else, including the content, can and will just come over as-is. Then, for the style, you just need to see if the attribute already exists, and if so, append that to your custom style. With just the code above:
<glabel id="foo" class="foo" style="width:100px">
<!-- child content here -->
</glabel>
Will result in:
<div id="foo" class="foo" style="display:inline-block;font-weight:bold;width:100px">
<!-- child content here -->
</div>
The child elements would need to be their own tag helpers if you need to do special stuff there. A tag helper only operates on the immediate tag itself, not an entire block of HTML. You can get the child content and manually modify it, but you'd be doing so as just a string, having to use stuff like regex. Suffice it to say, that would be less than ideal.
Chris Pratt (How do I reference another user properly?)
Unfortunately, you do misunderstand the question. I'm not having problems creating TagHelpers or understanding how they work. We have some 20-25 TagHelpers that we have developed, ranging from Dynamic lookups to our own fairly extensive and powerful grid. Example of grid usage below...
<ggrid id="grdTaskSearchResults"
url="Task_Search?handler=results&userguid=#Model.UserGUID&manager=#Model.Manager"
sortby="#Model.Opt_SortCol"
sortdir="#Model.Opt_SortDir"
pagesize="100"
style="height:100%; width:100%;">
<cols>
<coltemplate style="white-space:nowrap;">
<a onclick="gNewWindowAndTitle('View IT Call Log', null, null, 'Task_Summary?userguid=#Model.UserGUID&taskId={Task_ID}')" title="View IT Call Log"><img class="smallIcon" src="/Icons/Magnify.gif" /></a>
<gpdialog btnexit="Cancel" btnsubmitandclose="Save" title="Edit Call Log" url="Task_CRUD?userguid=#Model.UserGUID&manager=#Model.Manager&crud=u&taskId={Task_ID}" callback="ggridReload('grdTaskSearchResults')" linkicon="/Icons/Edit.gif" hideif="('#Model.Manager' !== 'true')" suppresstitle="true" />
<gpdialog btnexit="Cancel" btnsubmitandclose="Save" title="Add Note to Call Log" url="Task_Note_CRUD?userguid=#Model.UserGUID&taskId={Task_ID}" callback="ggridReload('grdTaskSearchResults')" linkicon="/Icons/NewAddition.gif" suppresstitle="true" />
<img class='smallIcon' src="/Icons/Exclamation.gif" alt='Not Responded yet!' hideif="{Responded}===true" />
</coltemplate>
<col heading="ID" fld="Task_ID" />
<col heading="Type" fld="Task_Type" style="white-space:nowrap;" />
<col heading="Status" fld="Task_Status" />
<coltemplate heading="Reported By">
<a target="_blank" href="https://gmis.info/entity/entity.asp?ec=1&code={Reported_By_ID}">{Reported_By_Name}</a>
</coltemplate>
<col heading="Date Entered" fld="Date_Entered" style="white-space:nowrap;" format="ddMMMyy" />
<col heading="NAB" fld="NAB_Initials" style="white-space:nowrap;" />
<coltemplate heading="Severity">
<span hideif="{Task_Status_ID}===3" style="color:{Severity_Color}; font-family:Webdings; font-size:10pt;">n</span><span hideif="{Task_Status_ID} == 3"> {Task_Severity}</span>
</coltemplate>
<col heading="Description" fld="Description" />
</cols>
<footer>
<gpdialog btnexit="Cancel" btnsubmitandclose="Save" title="Add New Call Log" url="Task_CRUD?userguid=#Model.UserGUID&manager=#Model.Manager&crud=c" callback="ggridReload('grdTaskSearchResults')" linkicon="/Icons/NewAddition.gif" />
</footer>
</ggrid>
That said, there's a couple of things in your code sample that I would like to look at in my own code. A potential improvement for us I think I can envisage in there. So in that regard, I thank you very much for your input.
No, my question is purely about the next step in the TagHelper story.
HtmlHelpers were written in c# and called in c#.
Taghelpers are written in c# and called in html markup.
Razor Components are written in html markup with some c# code inline/behind. However best implemented in Blazor using html markup. When called from within Razor pages, the call is made in c# code a little like HtmlHelpers were (a backward step for me).
What I would like to see somewhere in this story for the future, is a scenario wherby TagHelpers are written in html markup, with some c# code inline/behind, just like Razor components are now. And in use, the Taghelper called in markup as they are currently. I'm not suggesting that TagHelpers start to use c# on the client side. This is purely about how TagHelpers in their current guise and functionality... are written.
In essence, I am asking if anybody knows what the future holds for in terms of the next step for TagHelpers? Does this make sense?
I think a couple of years on, and I know the answer I was looking for. Moving forward at some point, blazor components are the next thing in line. I'm now considering converting all my taghelpers to blazor components in the future. At the moment, the only thing stopping me is the fact that you have to use some very verbose c# code within a razor page to use a blazor conponent. I'm hanging fire till they inevitably I feel, make it so you can use Html markup to consume blazor components within razor pages.

problem by <input asp-for='files' /> in Custom tag helper

I created a custom tagHelper.
But I have encountered a problem to develop the code snippet displayed(input asp-for="files" Exactly transmitted to the browser).
public override void Process(TagHelperContext context, TagHelperOutput output){
var form = #"<form id='uploadFileForm' method='post' enctype='multipart/form-data' >
<input asp-for='files' />
<input type = 'button' id ='btnUpload' value =' upload' />
</form > ";
output.PreContent.AppendHtmlLine(form);}
and my model :
[Required(ErrorMessage = "Please select a file.")]
[DataType(DataType.Upload)]
public IList<IFormFile> files { get; set; }
More explanation : When using
<input asp-for='files' />
in a view, the following code is finally generated in
browser:
<input type="file" data-val="true" data-val-required="Please select a file." id="files" multiple="multiple" name="files" />
Now, I do not know what to do in tagHelper to generate the same output in the above line by taghelper.
please help me
Take a look the docu (change the version if its not the right one): https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/authoring?view=aspnetcore-2.2
Gathering from the example there, what you are looking for should look like this
(untested example):
public override void Process(TagHelperContext context, TagHelperOutput output){
// Should already be input, but in case you want to change it to something else
output.TagName = "input";
// remove the old attribute
// You probably need to do something different if you want to carry over the attribute
output.Attributes.RemoveAll("asp-for");
output.Attributes.SetAttribute("type", "file");
output.Attributes.SetAttribute("data-val", "true");
output.Attributes.SetAttribute("data-val-required", "Please select a file.");
output.Attributes.SetAttribute("id", "files");
output.Attributes.SetAttribute("multiple", "multiple");
output.Attributes.SetAttribute("name", "files");
}
I am not sure whether you actually can use this for a predefined tag (like input), you might be better of if you create a custom one (something that does not exist already).
As you haven`t posted any example for the Annotation you use, lets say you change it to:
<custominput asp-for='files' />
then there should be something like this on you TagHelper Class.
[HtmlTargetElement("custominput", TagStructure = TagStructure.WithoutEndTag)]
The example above ignores your model, so I assume that if you want to use it you need to somehow provide it to your TagHelper Class, and change the SetAttribute lines accordingly.

Struts 2 single jsp page to execute multiple different methods

I am migrating from struts 1 to struts 2 framework. Based on struts 1 framework parameter=method attribute, I am able to execute different methods using the same jsp page by adding a hidden field "method".
How do I achieve the same in struts 2?
My Action class:
public class MyAction extends ActionSupport {
public String methodA() {
return "a";
}
public String methodB() {
return "b";
}
}
My JSP page
<s:form action="MyAction">
<s:select label="Method Name"
name="method"
headerKey="-1" headerValue="Select Method"
list="#{'01':'A', '02':'B', [...]}"
value="selectedMethod"
required="true"
/>
<s:submit type="button" name="submit" />
</s:form>
You could achieve that by changing the "action" url before submitting.
Check out Wildcard Method and Dynamic Method Invocation here
Though, the dynamic Method Invocation can be considered a Security Vulnerability

Struts 2 display tags

I have a JSP which has below tags the data in resultsList fed in some action and forwarded to below jsp here I would like to get the data back into the other action based on the checkbox selection. Please help, can do using Struts1 but don't like to turn back to Struts1 since started using Struts2.
<display:table class="displaytag" id="row" style="font-size:1.4em;" name="resultsList" requestURI="/SomePath.action">
<display:column property="businessType" title="Business Type"></display:column>
<display:column property="structure" title="Structure"></display:column>
<display:column property="tradeSubType" title="Trade Sub Type"></display:column>
<display:column property="businessGroup" title="Business Group"></display:column>
<display:column title="Select To Copy" align="center">
<s:checkbox name="selectToCopy" fieldValue="false" value="false" label="Check Me To Download"></s:checkbox>
</display:column>
</display:table>
The data will be fetched in one action and forwarded to the jsp where jsp contains above display tag and now I need to submit the form and action should receive the checked information to process further. Any help here is really appreciated, I can do it using Struts1 no doubt but would like to continue in Struts2.
I'm guessing your action class sends some domain objects from this type:
public class MyData {
private Integer id;
private String businessType;
//other params
//getter/setters
}
And your action class, that ist invoked before accessing the displaytag jsp page has a list of objects form type MyData:
public class MyDisplayTagAction extends ActionSupport {
private List<MyData> myDataList;
//other params
//getter/setter
public String execute() {
myDataList = getMyDataListFromSomewhere();
return SUCCESS;
}
}
The JSP should contain a form and a submit button. Moreover you have to define every data you want to send back as a field in that form. If the user is not allowed to change them, use hidden fields. The #attr.row.id access printing that id to the value. #attr is from ognl to access the variable row defined from displaytag. (For more info: Struts OGNL)
<s:form action="myStrutsPostAction" method="post">
<display:table name="myDataList" uid="row">
<display:column>
<s:checkbox name="resultsList[%{#attr.row_rowNum - 1}].selectToCopy" id="check%{#attr.row_rowNum - 1}" value="%{#attr.row.selectToCopy}"/>
</display:column>
<display:column>
<input type="hidden" name="resultsList[<s:property value='%{#attr.row_rowNum - 1}'/>]" value="<s:property value='%{#attr.row.businessType}' />"/>
<s:property value="%{#attr.row.businessType}"/>
</display:column
</display:table>
<s:submit>
</s:form>
The post action class (the one that takes the form request) should contain a list, that was defined in the <s:form> and struts will set only the the data into this list.
public class MyPostAction extends ActionSupport {
private List<MyData> resultsList = new ArrayList<>();
//getter/setter
}

How to get command link value(display name) from backing bean?

I have a p:commandLink in my xhtml with the value toggling between "Show"/"Hide".
Is there any way by which I can get the value of this commandlink from the backing bean?
I mean, I want to know what value the command link is showing currently i.e. Show/Hide?
To the point, the invoking component is just available in ActionEvent argument:
<h:commandLink id="show" value="Show it" actionListener="#{bean.toggle}" />
<h:commandLink id="hide" value="Hide it" actionListener="#{bean.toggle}" />
with
public void toggle(ActionEvent event) {
UIComponent component = event.getComponent();
String value = (String) component.getAttributes().get("value");
// ...
}
However, this is a poor design. Localizable text should absolutely not be used as part of business logic.
Rather, either hook on component ID:
String id = (String) component.getId();
or pass a method argument (EL 2.2 or JBoss EL required):
<h:commandLink id="show" value="Show it" actionListener="#{bean.toggle(true)}" />
<h:commandLink id="hide" value="Hide it" actionListener="#{bean.toggle(false)}" />
with
public void toggle(boolean show) {
this.show = show;
}
or even just call the setter method directly without the need for an additional action listener method:
<h:commandLink id="show" value="Show it" actionListener="#{bean.setShow(true)}" />
<h:commandLink id="hide" value="Hide it" actionListener="#{bean.setShow(false)}" />
As #BalusC suggested, your approach is not a good solution. But if you really want to do that, you can bind the component (p:commandLink) to your backingbean, as seen in What is the advantages of using binding attribute in JSF?.
After the component was bound, you can access the value attribute from the p:commandLink.

Resources