Wednesday, October 12, 2011

RAZOR cascading DropDownList

RAZOR


@Html.DropDownList("ddlElementCode",
TempData["ElementSelects"] as SelectList,
new { onchange = "populateValueTexts(this)" })




// Where the parameter “dropdown” is the first of the two

function populateValueTexts(dropdown) {
var myindex = dropdown.selectedIndex;
var selValue = dropdown.options[myindex].value
var xReq = jQuery.getJSON("ElementTexts",
{ elementCode: selValue },
null)
.complete(receiveValueTexts);
}

function receiveValueTexts(context, textStatus) {
var data = jQuery.parseJSON(context.responseText);

document.getElementById("ddlValueText").options.length = data.length;

jQuery.each(data, function (i, item) {
document.getElementById("ddlValueText").options[i].text = item.Text;
});
}

[AcceptVerbs(HttpVerbs.Get)]
public JsonResult ElementTexts(string elementCode)
{
Data d = new Data();

IList codes =
d.GetElementsByCode(Convert.ToInt32(elementCode));

SelectList items =
new SelectList((from c in codes select c.ELEMENT_VALUE_TXT).Distinct());

return Json(items, JsonRequestBehavior.AllowGet);
}

Tuesday, October 04, 2011

On getting NHibernate to Log the SQL

This feature is very nice. You get to see the SQL that is generated for you.

While logging is not rocket science, I don't want to learn it again on the next project, so I am saving it here. ( I am using Log4Net, but I am sure Enterprise Library or others will work similarly. )

// Configure log4net using the .config file in GLOBAL.ASAX
[assembly: XmlConfigurator(Watch = true)]
protected void Application_BeginRequest(object sender, EventArgs e)
{
XmlConfigurator.Configure();
}

In the Web.config

<log4net debug="true">
<!-- Define some output appenders -->
<appender name="trace" type="log4net.Appender.TraceAppender, log4net">
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n"/>
</layout>
</appender>
<appender name="console" type="log4net.Appender.ConsoleAppender, log4net">
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n"/>
</layout>
</appender>
<appender name="rollingFile" type="log4net.Appender.RollingFileAppender,log4net">
<param name="File" value="hib_log.txt"/>
<param name="AppendToFile" value="true"/>
<param name="maximumFileSize" value="500KB"/>
<param name="RollingStyle" value="Size"/>
<param name="DatePattern" value="yyyy.MM.dd"/>
<param name="StaticLogFileName" value="true"/>
<layout type="log4net.Layout.PatternLayout,log4net">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
</layout>
</appender>
<!-- Setup the root category, add the appenders and set the default priority -->
<root>
<priority value="DEBUG"/>
<appender-ref ref="rollingFile"/>
</root>
<logger name="NHibernate">
<level value="WARN"/>
</logger>
<logger name="NHibernate.SQL">
<level value="DEBUG"/>
</logger>
</log4net>

Monday, October 03, 2011

How to stream a File in MVC

In Classic ASP or ASP .Net, you can simply change the response type and start writing binary. In MVC you have a Controller method which returns an ActionResult. So this class will properly provide that :


public class BinaryResult : ActionResult
{
private byte[] _fileBinary;
private string _contentType;
private string _fileName;

public BinaryResult(byte[] fileBinary, string contentType, string fileName)
{
_fileBinary = fileBinary;
_contentType = contentType;
_fileName = fileName;
}

public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.Clear();
context.HttpContext.Response.ContentType = _contentType;
context.HttpContext.Response.AddHeader("Content-Disposition",
"filename=" + _fileName);

if (_fileBinary != null)
{
context.HttpContext.Response.BinaryWrite(_fileBinary);
}
}
}


In my case the only other challenge was getting the Byte array prepared, because I had to call Convert.FromBase64String, because of the way the data was stored.

Sunday, October 02, 2011

Developing for MVC4 using Razor and JSON

Just playing around this weekend, I wanted some data listings in a page that did not post back in MVC. While not such a big deal in regular ASP, MVC does not have page event handlers in a code-behind file. There is instead a Controller class that you can call in Routing code.



First : the client side javascript handler, this is what is called when the Controller method completes.



using (Ajax.BeginForm("SearchForms", "DBForms", new AjaxOptions() { OnSuccess="jsonFSearchComplete", OnFailure="searchFail" })) Then … function jsonFSearchComplete(context) { $("#DBFormsDiv").html(context.Data); }



Next, the Razor syntax for the page :


@{using (Ajax.BeginForm("JsonSearchRequests",
"Request",
new AjaxOptions() {
OnComplete = "searchComplete",
OnFailure= "searchFail"
}))

// Not including the whole form I created here, just
// labels and textboxes, etc..
}





Then the Controller code for getting the Partial view built and sent down (Got this from StackOverflow postings):


private string RenderRazorViewToString(string viewName)
{
using (var sw = new System.IO.StringWriter())
{
var viewResult =
ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
var viewContext =
new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}


For a form posting in a page, there must be a Controller method ( :


[AcceptVerbs(HttpVerbs.Post)]
public JsonResult JsonSearchRequests(string AccountNumber,
string Subfirm,
string RegistrationType)
{
Data d = new Data();

if (AccountNumber.Length > 0)
{
ViewData["Requests"] =
d.GetRequestsByAccount(AccountNumber);
}
else if (Subfirm.Length > 0)
{
ViewData["Requests"] =
d.GetDBRequests(Subfirm, RegistrationType)
.Skip(0).Take(100);
}
return Json(new { Data = RenderRazorViewToString("dbRequests") });
// Note the HttbVerb must be stated for Posting a form
}


For a link that a user can click in the page :



[AcceptVerbs(HttpVerbs.Get)]
public JsonResult JsonSelectDbRequest(string Id)
{
Data d = new Data();
ViewData["Generations"] = d.GetGenerations(Id);

return Json(new { Data = RenderRazorViewToString("dbGenerations") },
JsonRequestBehavior.AllowGet);
}

// Note the Http Verb for GET must be stated
}



Code for a Partial View of a list that does Ajax posting :


@Ajax.ActionLink("SELECT",
"JsonSelectDbRequest",
"DocRequest",
new { Id = req.REQUEST_ID },
new AjaxOptions() { OnComplete = "requestSelectComplete" });



EDIT: There is no need to include the old MVCAjax script files.