log traffic (including posted data) IIS 6.0 - windows server 2003 - asp.net-mvc

I understand that IIS logs parts of http request which I can access. I would like to log the whole http request for a short period of time. This means I would like to store the data being posted in its raw form. Is this possible using ISS’s logging facility or do I have to install another tool?
I have the following problem. I expose a ‘restful web service’ via asp.net mvc which stores posted data in a relational database. I tested the service via javascript. I url encoded some data and post them using jquery. The data is stored url encoded in the database as expected. Some clients also post data using unix and wget to the same web service. Unfortunately, the data is not stored url encoded (so we lose some data if it contains special characters like &). They claim that they send the data url encoded. Can this be a case true? Is the mechanics of wget post different to that of a javascript post? Is there a layer I overlook? I would like to double check whether the data send via wget is actually url encoded.
Thanks!
Best wishes,
Christian

You could create an MVC action filter, you could then have access to the Request object and pull out the interesting bits. You could then store this information in a text file or logging database. I've used this approach before and it works well if you thread the saving to database operation to not slow down the general request operation.
public class LogRequest : ActionFilterAttribute, IActionFilter
{
#region IActionFilter Members
void IActionFilter.OnActionExecuting(ActionExecutingContext var)
{
//code goes here
}
#endregion
}
[AcceptVerbs(HttpVerbs.Get)]
[LogRequest()]
public ActionResult Index()
{
return View();
}
You've kind of asked two questions here, I don't know about the second part.

Related

How can I design better communicate between application members and Web API and Signalr Hubs

I am working in a project which needs to communicate with users realtime. Basically I am following "synchronize pages over web api" path which is introducing in this video (also Brad Wilson has a nice video like this one) and the repository here for video.
My question is about mapping application members with their ConnectionIds which is producing by Signalr.
I used to be saving every signalr connection ID in a database table like:
ConnectionID
MemberID
ConnectionStatusID --> Connected(1), Disconnected(2), Reconnecting(3)
I was fetching member's connection IDs in most requests.
Then I decided to change this design. Now I am grouping every member with a unique string when OnConnected and OnDisconnected like this:
public override Task OnConnected()
{
Groups.Add(this.Context.ConnectionId, string.Format("MyHub_{0}",HubUser.MemberID));
return base.OnConnected();
}
public override Task OnDisconnected()
{
Groups.Remove(this.Context.ConnectionId, string.Format("MyHub_{0}",HubUser.MemberID));
return base.OnConnected();
}
Now I am not fetching anything from database about member connection IDs. It is only working over Web API for making synchronization between browser tabs.
I simply show how I am handling incoming Request and using Hub in Web API:
public HttpResponseMessage Example()
{
string msg = "Example to all";
//some other process
//Hub is an instance of a IHubContext
Hub.Clients.Group(string.Format("MyHub_{0}", HubUser.MemberID)).example(msg);
return Request.CreateResponse(HttpStatusCode.OK, msg);
}
So which one do you think is efficient way for using Signalr. What would you suggest is possibly better than these. Is making a dependency between hub and WebApi is a good design choice to go.
And also project will be deployed to multiple servers and Load Balancer will work in front of them (I am going to use Sql Backplane for this). There are few projects which must talk to Web API, indirectly to hub too.
I like your second solution as it should require less DB queries. It is no less efficient for SignalR to send to a group than it is for it to send to a connection id. You just need to ensure your group names (HubUser.MemberID) are unique and non-spoofable.
In SignalR 2.0, we make this pattern even easier: http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider
If your users' MemberIDs match up with their IPrincipal.Identity.Name, then you can just change all your code to use Clients.User(HubUser.MemberID)....
If you don't want to base your SignalR user id on the request's IPrincipal, you can provide your own IUserIdProvider and inject it using SignalR's dependency resolver.
http://www.asp.net/signalr/overview/signalr-20/extensibility/dependency-injection

Encrypt data passed in View Model

I have a simple post method in a MVC controller that checks whether the ModelState is valid then calls another method passing an instance of the model as a paramter. This model contains sensitive data that is easily obtained by looking at Fiddler. My goal is to somehow mask or encrypt this data so that it cannot be seen in an http trace.
I have seen posts suggesting to use Session or Temp variables but that is not an option in my case.
This is what the code looks like:
[HttpPost]
[ActionName("Search")]
[AccessControl(Xri)]
public ActionResult SearchPost(string string1, ViewModel model)
{
model.NoResults = false;
if (ModelState.IsValid)
{
if (ModelState.IsValid) return RedirectToAction("TargetAction", model);
}
}
[AccessControl(Xri)]
public ActionResult TargetAction(string arg, ViewModel viewModel)
{
.
.
.
}
Fiddler shows the following:
/TargetAction?id=01010101&date=08%2F14%2F2013%2000%3A00%3A00&To=08%2F21%2F2013%2000%3A00%3A00&param1=somevalue&param2=somevalue2
Is there a way to mask the url parameters shown here?
You're going to need to get SSL running on your server.
Without a server certificate from a trusted authority, there is very little you can do to encrypt the data over the wire. Why? Because you'd need to send encryption/decryption details in clear text before you start sending the data so that your client (likely JavaScript) could decode it.
Using a certificate and operating on 443 gives you built-in functionality from the server/browser that is hard to beat in a custom implementation.
If you just want to obscure the data (and put it beyond the level of most web users) you could always base64 encode the data, rather than encrypting it. Just be clear that you are NOT encrypting data and it is still possible to decode it. This approach is not a form of encryption.
If you decide to take that approach regardless, here are a few resources:
Client-side Encoding/Decoding
MSDN Reference on Encoding to Base64
Cheers.
You have two options for doing this:
Store the data on the server and give the user a token (e.g. a GUID) to pass along to retrieve the data. Since using the Session or TempData is not an option, you could store the viewmodel in the database, and then redirect the user with the token in the URL to retrieve it on the next request.
The other option would be to have the user pass the viewmodel in the URL as you're currently doing, but pass it in an encrypted format. For example, you could
serialize the model to JSON, encrypt it using one of .NET's built in encryption algorithms, and then redirect to the next action passing the encrypted string as your view model. Then you could change the target action to something like:
[AccessControl(Xri)]
public ActionResult TargetAction(string arg, string encryptedViewModel)
{
var decryptedString = Decrypt(encryptedViewModel) ; // supply the decrypt function to match your encryption
var viewModel = JsonConvert.DeserializeObject(decryptedString);
}

How to consume web API with authentication in Excel 2010

I have an exmaple of mvc 4 web API , and I want to consume it in Excel 2010. whats the easiest way to do it? I am thinking to pass in the username and password as string parameter if solution need to be complicated.
[Authorize]
public class AccountBalanceApiController : ApiController
{
//http://localhost/FTAccounting/api/AccountBalanceApi?companyId=16&fiscalYear=2012
public Dictionary<int, TrialBalanceAccountSummaryModel> Get(int companyId, int fiscalYear)
{
return AccountBalance.GetTrialBalance(companyId, fiscalYear);
}
}
Update: Web service Authentication is not possible in Excel. Reference from http://cwebbbi.wordpress.com/2012/07/31/using-the-webservice-function-in-excel-2013/
web service Authentication is not possible in Excel. reference from http://cwebbbi.wordpress.com/2012/07/31/using-the-webservice-function-in-excel-2013/
In modern Excel you can use Get & Transform to connect to Web API with authorisation. Select Data tab, then in the Get & Transform group New Query -> From Other Sources -> From Web (Note: do not confuse this with 'From Web' button which is directly in the Get External Data group). Enter your endpoint URL (you can also define request headers here) and in the next step you will be asked for authentication method.

ASP.NET MVC Read Raw JSON Post Data

This is driving me crazy. I'm using ASP.NET MVC. I have a controller with an HttpPost action that acts as a callback URL that is called by another server (not under my control). I want to dynamically read JSON posted to it without using WebAPI or Model Binding. The URL also has a query string parameter passed to it.
The callback URL looks something like this:
http://domain.com/callback?secret=1234
I've tried reading the posted input using:
[HttpPost]
public ActionResult Callback( String secret )
{
String jsonData = new StreamReader(this.Request.InputStream).ReadToEnd();
// ...
}
However "jsonData" is always null or empty.
I just want to get the posted input and stick it into JsonFx so I can dynamically access the contents. Any ideas on how to do this the easiest possible way?
UPDATE
I've discovered the following ...
While the above DOES NOT work (jsonData will be null or empty), the following DOES if I configure what little options I have on the calling server so as to omit the "secret" query string parameter, which is about all I can do on that end since it is not my server. In this case, jsonData will have the correct posted JSON string:
[HttpPost]
public ActionResult Callback( /* String secret */ )
{
String jsonData = new StreamReader(this.Request.InputStream).ReadToEnd();
// ...
}
This is very frustrating to work around and I don't know an easy way to accept both a query string and posted JSON data on a standard MVC controller.
I have a "callback controller" with Action methods that accept various data (via GET, via form POST, via JSON POST, via JSON POST w/ a Query String, etc.) from different third-party servers. These are merchant-type callbacks where I have no control over the formats or methods used to convey information. I just need to accept the callbacks and process the information that should be there.
All of it works fine in my Controller, except the case of "JSON POST w/ a Query String".
This appears (at least to me) to be a shortcoming in standard ASP.NET MVC controllers. ???
Can anyone suggest a solution to this that can be used in a standard ASP.NET MVC controller?
Your initial approach should work if you take into consideration the fact, that ASP.NET MVC model binding has already read the stream, so you should rewind it:
[HttpPost]
public ActionResult Callback(string secret)
{
Request.InputStream.Seek(0, SeekOrigin.Begin);
string jsonData = new StreamReader(Request.InputStream).ReadToEnd();
// ...
}
Reset the position to Zero before reading the stream.
Request.InputStream.Position = 0
For ASP.NET Core 2,this works for me.
[HttpPost]
public ActionResult RawTest() {
using (StreamReader reader = new StreamReader(Request.Body, Encoding.UTF8))
{
string content = reader.ReadToEndAsync().Result;
//...
}
//...
}

How to only allow access from WCF Data Service ServiceOperation

I use WCF with my ASP.NET MVC app, my data service get data from my (EF 4.1) .mdf file. But there is some feild that I want to show with authentication, for example:
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Exercies", EntitySetRights.All);
config.SetServiceOperationAccessRule("GetAllExercies", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
[WebGet]
public IQueryable<Exercise> GetAllExercies(string name, string pass)
{
if (Membership.ValidateUser(name, pass))
return CurrentDataSource.Exercies;
else
return CurrentDataSource.Exercies.Where(e => e.Public == true);
}
Now when user access httx://localhost/MyService.svc/Exercies, they can get everything although they are not given the username and pass.
My temporary solution is re name GetAllExercies to just Exercies but I not sure is there any better way...
Yes, there is a better solution: query interceptors. In fact using the same name for entity set and service operation tends to lead to problems in certain scenarios (the $metadata is "confusing" for the clients). It's also not 100% secure (doesn't prevent accessing the entity through some navigation property if you have that).
See this http://msdn.microsoft.com/en-us/library/dd744842.aspx. The idea is that you make the auth filter part of the entity set query, and WCF DS Service makes sure that it will be used everywhere that entity set is accessed.

Resources